From 472fb128a1ab46a76cd76d1e0b8d9cce0762dad8 Mon Sep 17 00:00:00 2001
From: MetaMask Bot
Date: Fri, 6 Sep 2024 18:41:26 +0000
Subject: [PATCH 01/43] Version v12.3.0
---
CHANGELOG.md | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++-
package.json | 2 +-
2 files changed, 361 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 57c1da0402c6..b755f577c9b8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,364 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [12.3.0]
+### Uncategorized
+- Merge branch 'Version-v12.2.0' into Version-v12.3.0
+- Merge remote-tracking branch 'origin/master' into Version-v12.2.0
+- CherryPick: "fix: issue where `wallet_addEtherumChain` was incorrectly enforcing inclusion of a blockExplorerUrls property which is not required (#26938)" ([#26938](https://github.com/MetaMask/metamask-extension/pull/26938))
+- fix: update notifications events (#26807) ([#26807](https://github.com/MetaMask/metamask-extension/pull/26807))
+- Update v12.2.0 with changes from v12.1.2 ([#26895](https://github.com/MetaMask/metamask-extension/pull/26895))
+- Merge remote-tracking branch 'origin/master' into sync-v12.1.2
+- perf(cherry-pick): use an interstitial page to load `popup.html`; load scripts using `defer`ed script tags (#26555) ([#26555](https://github.com/MetaMask/metamask-extension/pull/26555))
+- v12.2.0 sync v12.1.1 ([#26842](https://github.com/MetaMask/metamask-extension/pull/26842))
+- Merge branch 'Version-v12.2.0' into v12.2.0-sync-v12.1.1
+- ci: Prevent E2E timeouts on release changes (#26846) [cherry-pick] ([#26846](https://github.com/MetaMask/metamask-extension/pull/26846))
+- Fix type error
+- Fix changelog merge conflicts
+- Update LavaMoat policies
+- Run yarn dedupe
+- Update LavaMoat policies
+- Merge branch 'Version-v12.2.0' into v12.2.0-sync-v12.1.1
+- chore: MMI adds cherry pick for PR 25967 ([#26736](https://github.com/MetaMask/metamask-extension/pull/26736))
+- Merge remote-tracking branch 'origin/Version-v12.2.0' into v12.2.0-sync-v12.1.1
+- Merge remote-tracking branch 'origin/master' into v12.2.0-sync-v12.1.1
+- fix(cherry-pick): remove BTC accounts from send flow (#26271) ([#26271](https://github.com/MetaMask/metamask-extension/pull/26271))
+- feat(cherry-pick): support creation of Bitcoin testnet accounts (#25772) ([#25772](https://github.com/MetaMask/metamask-extension/pull/25772))
+- fix(cherry-pick): remove btc account from permission connect lists (#25980) ([#25980](https://github.com/MetaMask/metamask-extension/pull/25980))
+- fix(cherry-pick): remove submitRequest from dapp permission (#26319) ([#26319](https://github.com/MetaMask/metamask-extension/pull/26319))
+- chore: update @metamask/bitcoin-wallet-snap to 0.5.0 ([#26701](https://github.com/MetaMask/metamask-extension/pull/26701))
+- chore: update @metamask/bitcoin-wallet-snap to 0.4.0 ([#26229](https://github.com/MetaMask/metamask-extension/pull/26229))
+- chore: update @metamask/bitcoin-wallet-snap to 0.3.0 ([#26168](https://github.com/MetaMask/metamask-extension/pull/26168))
+- chore: update Bitcoin Snap to version 0.2.5 ([#26058](https://github.com/MetaMask/metamask-extension/pull/26058))
+- fix(multichain): use accounts{Added,Removed} to fetch/clear balances ([#25884](https://github.com/MetaMask/metamask-extension/pull/25884))
+- feat: add BTC support survey link ([#25875](https://github.com/MetaMask/metamask-extension/pull/25875))
+- Cherrypick flaky test fix 12.2.0 ([#26747](https://github.com/MetaMask/metamask-extension/pull/26747))
+- chore: cherry pick remove token and nft detection modals (#26403) ([#26403](https://github.com/MetaMask/metamask-extension/pull/26403))
+- Synchronize v12.2.0 RC with v12.1.0 ([#26729](https://github.com/MetaMask/metamask-extension/pull/26729))
+- Merge remote-tracking branch 'origin/master' into v12.2.0-sync-master
+- v12.2.0 sync with v12.1.0 ([#26695](https://github.com/MetaMask/metamask-extension/pull/26695))
+- Fix Sentry state merge conflict error
+- fix cherry-pick test: UX: Multichain: Add E2E for signaling network change from Netwo… ([#26704](https://github.com/MetaMask/metamask-extension/pull/26704))
+- test: Removed step from e2e tests ([#25910](https://github.com/MetaMask/metamask-extension/pull/25910))
+- Update LavaMoat policies
+- Resolve changelog conflicts
+- DResolve audit advisory
+- Merge remote-tracking branch 'origin/Version-v12.1.0' into v12.2.0-sync-with-v12.1.0
+- Patch fix for initial connections in preinstalled Snaps ([#26602](https://github.com/MetaMask/metamask-extension/pull/26602))
+- add version in changelog/package.json files ([#25766](https://github.com/MetaMask/metamask-extension/pull/25766))
+- chore: Master sync ([#26395](https://github.com/MetaMask/metamask-extension/pull/26395))
+- chore: Bump Snaps packages ([#26086](https://github.com/MetaMask/metamask-extension/pull/26086))
+- fix: Improve AccountListMenu/Item performance ([#26379](https://github.com/MetaMask/metamask-extension/pull/26379))
+- fix: Codespaces `corepack enable` ([#25161](https://github.com/MetaMask/metamask-extension/pull/25161))
+- fix: display toast message if user quickly sends transaction on different networks ([#26114](https://github.com/MetaMask/metamask-extension/pull/26114))
+- fix: problem with origins in the Snaps permission UI ([#26422](https://github.com/MetaMask/metamask-extension/pull/26422))
+- feat: Add abstraction for Snaps permissions ([#25175](https://github.com/MetaMask/metamask-extension/pull/25175))
+- test: add transaction contract interaction integration tests ([#26272](https://github.com/MetaMask/metamask-extension/pull/26272))
+- fix: timeout and "Rerun failed tests" ([#26239](https://github.com/MetaMask/metamask-extension/pull/26239))
+- chore: migrate BridgeController to BaseController v2 ([#26109](https://github.com/MetaMask/metamask-extension/pull/26109))
+- feat: Enable why did you render ([#26339](https://github.com/MetaMask/metamask-extension/pull/26339))
+- fix: Delete invalid `SelectedNetworkController` state ([#26428](https://github.com/MetaMask/metamask-extension/pull/26428))
+- test: ensure bridge button handles clicks according to feature flags ([#25812](https://github.com/MetaMask/metamask-extension/pull/25812))
+- build(webpack): polyfill `setImmediate` ([#26398](https://github.com/MetaMask/metamask-extension/pull/26398))
+- feat: feature-flagged cross-chain swaps route [METABRIDGE-867] ([#25811](https://github.com/MetaMask/metamask-extension/pull/25811))
+- chore: Remove i18n translations from Developer Options Settings Page ([#26380](https://github.com/MetaMask/metamask-extension/pull/26380))
+- fix: Do not break application if no token details are found using getTokenStandardAndDetails ([#26324](https://github.com/MetaMask/metamask-extension/pull/26324))
+- fix: Flaky contract interaction test ([#26420](https://github.com/MetaMask/metamask-extension/pull/26420))
+- fix: Enter key on Create Account checkbox should not trigger show/hide ([#26394](https://github.com/MetaMask/metamask-extension/pull/26394))
+- fix: notifications use better events ([#26410](https://github.com/MetaMask/metamask-extension/pull/26410))
+- fix: Restore snaps-controllers version following patch ([#26412](https://github.com/MetaMask/metamask-extension/pull/26412))
+- fix: Improve hex copy button ([#26384](https://github.com/MetaMask/metamask-extension/pull/26384))
+- refactor: use core profile syncing controllers. ([#26370](https://github.com/MetaMask/metamask-extension/pull/26370))
+- test: snap account contract interaction ([#26234](https://github.com/MetaMask/metamask-extension/pull/26234))
+- feat: updated SSK version in e2e and added test for creating multiple… ([#26378](https://github.com/MetaMask/metamask-extension/pull/26378))
+- Merge origin/develop into master-sync
+- chore: MMI move duck and selector to TS ([#26125](https://github.com/MetaMask/metamask-extension/pull/26125))
+- refactor(notifications): use contentful package as dev dependency ([#26381](https://github.com/MetaMask/metamask-extension/pull/26381))
+- fix: remove submitRequest from dapp permission ([#26319](https://github.com/MetaMask/metamask-extension/pull/26319))
+- feat: Add integration test for blockaid on contract interaction ([#26366](https://github.com/MetaMask/metamask-extension/pull/26366))
+- refactor: add performance tracing infrastructure ([#26044](https://github.com/MetaMask/metamask-extension/pull/26044))
+- refactor: replace deprecated mixins with Text component in slippage-buttons ([#25638](https://github.com/MetaMask/metamask-extension/pull/25638))
+- refactor: replace deprecated mixins with text component in loading-swaps-quotes ([#25553](https://github.com/MetaMask/metamask-extension/pull/25553))
+- feat: Add metrics for alerts (transactions redesign) ([#26121](https://github.com/MetaMask/metamask-extension/pull/26121))
+- fix(25350): fix flakey token importing e2e test ([#26351](https://github.com/MetaMask/metamask-extension/pull/26351))
+- fix: enable Save button on Add Contact page for address input ([#26155](https://github.com/MetaMask/metamask-extension/pull/26155))
+- test: Add test for migration 120.2 and fix docs ([#26333](https://github.com/MetaMask/metamask-extension/pull/26333))
+- chore: normalize separator in `content` on the `viewport` `meta` tag ([#26268](https://github.com/MetaMask/metamask-extension/pull/26268))
+- fix: Stop logging pipeline stream errors in the service worker if they match 'Premature close' ([#26336](https://github.com/MetaMask/metamask-extension/pull/26336))
+- build: add alternative build process to enable faster developer builds ([#22506](https://github.com/MetaMask/metamask-extension/pull/22506))
+- fix: issue where `setNetworkClientIdForDomain` was called without checking whether the origin was eligible for setting its own network ([#26323](https://github.com/MetaMask/metamask-extension/pull/26323))
+- fix: get permit and order signatures token decimals ([#26292](https://github.com/MetaMask/metamask-extension/pull/26292))
+- feat: Update Redesign Signature Permit to show ellipsis at max 15 digits ([#26227](https://github.com/MetaMask/metamask-extension/pull/26227))
+- fix: remove the ability to send to btc accounts in send page ([#26271](https://github.com/MetaMask/metamask-extension/pull/26271))
+- fix: Adding migration 125 to remove Deprecated TxController Key from state ([#26267](https://github.com/MetaMask/metamask-extension/pull/26267))
+- fix: Revert "fix: remove submitRequest from dapp permission" ([#26293](https://github.com/MetaMask/metamask-extension/pull/26293))
+- refactor: convert `icon-factory.js` to typescript ([#23823](https://github.com/MetaMask/metamask-extension/pull/23823))
+- fix(26065): remove persisted state mostRecentRetrievedState after initialization if no errors ([#26206](https://github.com/MetaMask/metamask-extension/pull/26206))
+- refactor: ENABLE_MV3 flag cleanup ([#26059](https://github.com/MetaMask/metamask-extension/pull/26059))
+- test: fix flaky test Import flow @no-mmi Import wallet using Secret Recovery Phrase ([#26275](https://github.com/MetaMask/metamask-extension/pull/26275))
+- chore: Fully remove `eth_sign` ([#24756](https://github.com/MetaMask/metamask-extension/pull/24756))
+- fix: remove submitRequest from dapp permission ([#26276](https://github.com/MetaMask/metamask-extension/pull/26276))
+- chore: Update `actions/cache` from v3 to v4 ([#26020](https://github.com/MetaMask/metamask-extension/pull/26020))
+- feat: QR-based add NGRAVE ZERO Hardware ([#25080](https://github.com/MetaMask/metamask-extension/pull/25080))
+- fix: Fix GitHub release description ([#26247](https://github.com/MetaMask/metamask-extension/pull/26247))
+- feat(btc): use new snap account flow for Bitcoin accounts ([#26183](https://github.com/MetaMask/metamask-extension/pull/26183))
+- refactor: replace deprecated mixins with text component in transaction-confirmed ([#25551](https://github.com/MetaMask/metamask-extension/pull/25551))
+- fix: improve warning in add network modal ([#26250](https://github.com/MetaMask/metamask-extension/pull/26250))
+- fix: Fix `create_release_pull_request` OOM error ([#26249](https://github.com/MetaMask/metamask-extension/pull/26249))
+- chore: Create a story for TokenCurrencyDisplay component ([#26172](https://github.com/MetaMask/metamask-extension/pull/26172))
+- chore: refactoring onboarding to remove deprecated components ([#26207](https://github.com/MetaMask/metamask-extension/pull/26207))
+- fix: Fix CircleCI `create_release_pull_request` job ([#26246](https://github.com/MetaMask/metamask-extension/pull/26246))
+- fix: flaky test `Import flow @no-mmi Import Account using json file` ([#26240](https://github.com/MetaMask/metamask-extension/pull/26240))
+- fix: sentry sessions ([#26192](https://github.com/MetaMask/metamask-extension/pull/26192))
+- test: [Page Object Model] rename process to flow ([#26228](https://github.com/MetaMask/metamask-extension/pull/26228))
+- test: header integration test for contract interaction ([#25981](https://github.com/MetaMask/metamask-extension/pull/25981))
+- chore: Pass along hashed `rpcUrl` during `CustomNetworkAdded` event ([#26203](https://github.com/MetaMask/metamask-extension/pull/26203))
+- chore: Create a story for PageContainerHeader component ([#26031](https://github.com/MetaMask/metamask-extension/pull/26031))
+- chore: Create a story for GasTiming component ([#25557](https://github.com/MetaMask/metamask-extension/pull/25557))
+- New Crowdin translations by Github Action ([#26230](https://github.com/MetaMask/metamask-extension/pull/26230))
+- chore: update @metamask/bitcoin-wallet-snap to 0.4.0 ([#26229](https://github.com/MetaMask/metamask-extension/pull/26229))
+- fix: flaky test `Sentry errors before initialization, after opting into metrics @no-mmi should send error events in background` ([#26216](https://github.com/MetaMask/metamask-extension/pull/26216))
+- chore: Create a story for NftCollectionImage component ([#26069](https://github.com/MetaMask/metamask-extension/pull/26069))
+- fix: update icons ([#26180](https://github.com/MetaMask/metamask-extension/pull/26180))
+- refactor: replace Typography with Text component in restore-vault.js ([#25636](https://github.com/MetaMask/metamask-extension/pull/25636))
+- chore: Create a story for convert-token-to-nft-modal component ([#25561](https://github.com/MetaMask/metamask-extension/pull/25561))
+- refactor: replace deprecated mixins with Text component in qr-code-view ([#25637](https://github.com/MetaMask/metamask-extension/pull/25637))
+- test: Add manual scenario for network polling scenario ([#26195](https://github.com/MetaMask/metamask-extension/pull/26195))
+- feat: Add experimental settings toggle for transactions redesign ([#26010](https://github.com/MetaMask/metamask-extension/pull/26010))
+- feat: Support Permit variants: PermitSingle, PermitBatch, PermitTransferFrom, PermitBatchTransferFrom, TradeOrder, Seaport ([#26107](https://github.com/MetaMask/metamask-extension/pull/26107))
+- feat: updated dapp permission screen ([#25703](https://github.com/MetaMask/metamask-extension/pull/25703))
+- fix: improve performance in large signature request confirmations ([#26209](https://github.com/MetaMask/metamask-extension/pull/26209))
+- refactor: remove password manager mention ([#25985](https://github.com/MetaMask/metamask-extension/pull/25985))
+- New Crowdin translations by Github Action ([#25939](https://github.com/MetaMask/metamask-extension/pull/25939))
+- chore: remove opera manifest files as they are not used ([#26200](https://github.com/MetaMask/metamask-extension/pull/26200))
+- fix(deps): bump fast-xml-parser from 4.3.4 to 4.4.1. ([#26202](https://github.com/MetaMask/metamask-extension/pull/26202))
+- test: [Snaps E2E] remove unnecessary steps from snaps UI Images test ([#25640](https://github.com/MetaMask/metamask-extension/pull/25640))
+- fix: truncate long tokenId ([#26179](https://github.com/MetaMask/metamask-extension/pull/26179))
+- chore: Add en_GB locale ([#26196](https://github.com/MetaMask/metamask-extension/pull/26196))
+- chore: upgrade to Sentry 8 ([#25999](https://github.com/MetaMask/metamask-extension/pull/25999))
+- refactor: add unlock checks for notification related controllers ([#26189](https://github.com/MetaMask/metamask-extension/pull/26189))
+- fix: interpret multipart errors correctly and allow ignore ([#26113](https://github.com/MetaMask/metamask-extension/pull/26113))
+- feat: migrate global unit tests from Mocha to Jest ([#26104](https://github.com/MetaMask/metamask-extension/pull/26104))
+- fix: node being setup twice ([#26052](https://github.com/MetaMask/metamask-extension/pull/26052))
+- fix: setupControllerConnection outstream end event listener ([#26141](https://github.com/MetaMask/metamask-extension/pull/26141))
+- fix: Address performance issues with 'Portfolio Dashboard' loading in test environment ([#26182](https://github.com/MetaMask/metamask-extension/pull/26182))
+- chore: migrating interactive-replacement-token-page to ts ([#26115](https://github.com/MetaMask/metamask-extension/pull/26115))
+- feat: (cherry-pick)(Version v12.2.0) Migration #122 set redesignedConfirmationsEnabled to true ([#26139](https://github.com/MetaMask/metamask-extension/pull/26139))
+- chore: update @metamask/bitcoin-wallet-snap to 0.3.0 ([#26168](https://github.com/MetaMask/metamask-extension/pull/26168))
+- test: fix potential api-spec test race condition when adding to task queue ([#26171](https://github.com/MetaMask/metamask-extension/pull/26171))
+- fix(user-preference-currency-display): remove unused prop ethLogoHeight ([#24517](https://github.com/MetaMask/metamask-extension/pull/24517))
+- fix: update logos for flare-mainnet and songbird ([#25560](https://github.com/MetaMask/metamask-extension/pull/25560))
+- feat: define account name during creation ([#25191](https://github.com/MetaMask/metamask-extension/pull/25191))
+- chore: MMI move custody component to TS ([#26096](https://github.com/MetaMask/metamask-extension/pull/26096))
+- chore: add portfolio ephemeral domain URL ([#26163](https://github.com/MetaMask/metamask-extension/pull/26163))
+- fix: Flaky test `4byte setting ` ([#26111](https://github.com/MetaMask/metamask-extension/pull/26111))
+- fix: PPOM blockaid update ([#26154](https://github.com/MetaMask/metamask-extension/pull/26154))
+- fix: flaky BTC e2e tests ([#26082](https://github.com/MetaMask/metamask-extension/pull/26082))
+- chore: Add extra event props ([#26123](https://github.com/MetaMask/metamask-extension/pull/26123))
+- refactor: fix event names used to track notifications ([#25521](https://github.com/MetaMask/metamask-extension/pull/25521))
+- test: [Snaps E2E] Create test for snap dialog JSX functionality ([#25493](https://github.com/MetaMask/metamask-extension/pull/25493))
+- chore: update BNB logos ([#26140](https://github.com/MetaMask/metamask-extension/pull/26140))
+- fix: enable siwe redesign ([#26136](https://github.com/MetaMask/metamask-extension/pull/26136))
+- chore: cleanup `.prettierignore` file ([#24828](https://github.com/MetaMask/metamask-extension/pull/24828))
+- chore: Bump `@metamask/ens-controller` to v12 ([#26127](https://github.com/MetaMask/metamask-extension/pull/26127))
+- chore: Bump `@metamask/transaction-controller` to v34 ([#26124](https://github.com/MetaMask/metamask-extension/pull/26124))
+- Revert "test: Adding e2e for SIWE and re-enabling redesign for SIWE (#25831)" ([#25831](https://github.com/MetaMask/metamask-extension/pull/25831))
+- chore: Create a story for Snackbar component ([#25515](https://github.com/MetaMask/metamask-extension/pull/25515))
+- fix: add new helper function for `openMenuSafe` to mitigate all ocurrences for opening menu with MMI build ([#26079](https://github.com/MetaMask/metamask-extension/pull/26079))
+- test: Adding e2e for SIWE and re-enabling redesign for SIWE (#25831) ([#25831](https://github.com/MetaMask/metamask-extension/pull/25831))
+- feat: make add-team-label use the reusable workflow ([#25807](https://github.com/MetaMask/metamask-extension/pull/25807))
+- chore: MMI-5301 adds enums for custody type and status ([#26006](https://github.com/MetaMask/metamask-extension/pull/26006))
+- feat: Move ENABLE_CONFIRMATION_REDESIGN feature flag to the developer… ([#26095](https://github.com/MetaMask/metamask-extension/pull/26095))
+- fix: remove btc account from permission connect lists ([#25980](https://github.com/MetaMask/metamask-extension/pull/25980))
+- feat: update network list item to include start accessory and end ([#25507](https://github.com/MetaMask/metamask-extension/pull/25507))
+- chore: mmi 5305 mmi pages typescript migration ([#26081](https://github.com/MetaMask/metamask-extension/pull/26081))
+- fix: Move Snaps hooks out of code fence ([#26120](https://github.com/MetaMask/metamask-extension/pull/26120))
+- feat: Mitigate risk for distracted users on queued transactions from different dApps ([#25852](https://github.com/MetaMask/metamask-extension/pull/25852))
+- fix: lock Chrome version to 126 (#26101) ([#26101](https://github.com/MetaMask/metamask-extension/pull/26101))
+- feat: Add metrics event for advanced details section toggling ([#26083](https://github.com/MetaMask/metamask-extension/pull/26083))
+- fix: display link to privacy-policy explanation in onboarding flow ([#26038](https://github.com/MetaMask/metamask-extension/pull/26038))
+- chore: Create a story for InvalidCustomNetworkAlert component ([#25600](https://github.com/MetaMask/metamask-extension/pull/25600))
+- fix: number formatting on swap + send tx detail ([#26029](https://github.com/MetaMask/metamask-extension/pull/26029))
+- fix: Flaky test `Account Custom Name..` ([#26062](https://github.com/MetaMask/metamask-extension/pull/26062))
+- fix: snap flakiness on `installSnapSimpleKeyring` function ([#26039](https://github.com/MetaMask/metamask-extension/pull/26039))
+- fix: lock Chrome version to 126 ([#26101](https://github.com/MetaMask/metamask-extension/pull/26101))
+- fix: remove halo for tokens ([#26016](https://github.com/MetaMask/metamask-extension/pull/26016))
+- refactor: replace typography with text component in creation-successful.js ([#25552](https://github.com/MetaMask/metamask-extension/pull/25552))
+- fix: `vault decryption` broken tests due to update on window handling ([#26074](https://github.com/MetaMask/metamask-extension/pull/26074))
+- docs: Centralize Author/Team Mapping for Commit Tracking ([#25986](https://github.com/MetaMask/metamask-extension/pull/25986))
+- fix: flaky test: Check the toggle for hex data ([#25899](https://github.com/MetaMask/metamask-extension/pull/25899))
+- chore: migrated institutional ui components to ts ([#25858](https://github.com/MetaMask/metamask-extension/pull/25858))
+- chore: removed unused component ([#26000](https://github.com/MetaMask/metamask-extension/pull/26000))
+- chore: update Bitcoin Snap to version 0.2.5 ([#26058](https://github.com/MetaMask/metamask-extension/pull/26058))
+- refactor: replace Typography with Text component in metametrics.js ([#25630](https://github.com/MetaMask/metamask-extension/pull/25630))
+- refactor: replace typography with text component in review recovery phrase ([#25265](https://github.com/MetaMask/metamask-extension/pull/25265))
+- test: new switchToWindowWithTitle w/ Extension communication ([#25362](https://github.com/MetaMask/metamask-extension/pull/25362))
+- ci: Trimming the gitdiff output before writing to output file ([#26057](https://github.com/MetaMask/metamask-extension/pull/26057))
+- chore: tweak send page styling ([#25982](https://github.com/MetaMask/metamask-extension/pull/25982))
+- fix: mmi flaky tests `Reveal SRP through settings completes quiz and reveals SRP QR after wrong answers` , `Sign Typed Data Signature Request can initiate and reject a Signature Request of Sign Typed Data`, `Sign Typed Data Signature Request can queue multiple Signature Requests of Sign Typed Data and confirm` ([#26055](https://github.com/MetaMask/metamask-extension/pull/26055))
+- chore: Create a story for IconButton component ([#25277](https://github.com/MetaMask/metamask-extension/pull/25277))
+- fix: center token icon ([#26013](https://github.com/MetaMask/metamask-extension/pull/26013))
+- fix: flaky test `Import flow @no-mmi Import wallet using Secret Recovery Phrase with pasting word by word` ([#26049](https://github.com/MetaMask/metamask-extension/pull/26049))
+- fix: flaky test 25912 ([#25913](https://github.com/MetaMask/metamask-extension/pull/25913))
+- chore: add privacy query params to portfolio navigation ([#25958](https://github.com/MetaMask/metamask-extension/pull/25958))
+- fix: (cherry-pick) Remove special reject button case from api spec tests (#26048) ([#26048](https://github.com/MetaMask/metamask-extension/pull/26048))
+- chore: Temporarily disable Playwright Swaps tests ([#26050](https://github.com/MetaMask/metamask-extension/pull/26050))
+- fix: Remove special reject button case from api spec tests ([#26048](https://github.com/MetaMask/metamask-extension/pull/26048))
+- test(e2e): unlock trezor account ([#25824](https://github.com/MetaMask/metamask-extension/pull/25824))
+- fix: Flaky "Signature Approved Event" e2e test ([#26040](https://github.com/MetaMask/metamask-extension/pull/26040))
+- feat: Migration #122 set redesignedConfirmationsEnabled to true ([#25769](https://github.com/MetaMask/metamask-extension/pull/25769))
+- fix: Revert "refactor: use withKeyring method (#25435)" ([#25435](https://github.com/MetaMask/metamask-extension/pull/25435))
+- fix: :label: update the text in the popup to enable notifications ([#26026](https://github.com/MetaMask/metamask-extension/pull/26026))
+- fix: map the supported block explorers ([#25908](https://github.com/MetaMask/metamask-extension/pull/25908))
+- fix: update css for modals ([#25961](https://github.com/MetaMask/metamask-extension/pull/25961))
+- fix: Fix permssions for `update-attributions` workflow ([#26019](https://github.com/MetaMask/metamask-extension/pull/26019))
+- fix: add migration for profile syncing controller ([#26004](https://github.com/MetaMask/metamask-extension/pull/26004))
+- test: Adding e2e for SIWE and re-enabling redesign for SIWE ([#25831](https://github.com/MetaMask/metamask-extension/pull/25831))
+- test: UX: Multichain: Add E2E for signaling network change from Network menu to dapp, Autoswitching networks ([#25765](https://github.com/MetaMask/metamask-extension/pull/25765))
+- feat: Move ENABLE_CONFIRMATION_REDESIGN feature flag to the developer settings page ([#25520](https://github.com/MetaMask/metamask-extension/pull/25520))
+- fix: `yarn:start:test:flask` is broken `Lavapack is not defined` ([#25995](https://github.com/MetaMask/metamask-extension/pull/25995))
+- feat: add utility function to get supported chains from the Security Alerts API ([#25716](https://github.com/MetaMask/metamask-extension/pull/25716))
+- fix: `vault-decryption` test since the order of announcement modals changed ([#25997](https://github.com/MetaMask/metamask-extension/pull/25997))
+- fix: updated switch to this account condition ([#25609](https://github.com/MetaMask/metamask-extension/pull/25609))
+- fix: flaky test Settings Redirects to ENS domains when user inputs ENS into address bar ([#25782](https://github.com/MetaMask/metamask-extension/pull/25782))
+- chore: MMI-5248 introduce the token allowance functionality for MMI ([#25967](https://github.com/MetaMask/metamask-extension/pull/25967))
+- fix: vertically align asset image ([#25988](https://github.com/MetaMask/metamask-extension/pull/25988))
+- feat: Adding state per window in e2e, excluding null state ([#25900](https://github.com/MetaMask/metamask-extension/pull/25900))
+- fix: attribution link ([#25947](https://github.com/MetaMask/metamask-extension/pull/25947))
+- feat: Enable hardware wallets for smart transactions in swaps ([#25742](https://github.com/MetaMask/metamask-extension/pull/25742))
+- fix: fix link redirection ([#25983](https://github.com/MetaMask/metamask-extension/pull/25983))
+- fix: fix overlapping modals ([#25962](https://github.com/MetaMask/metamask-extension/pull/25962))
+- feat: Show the Close extension button on the Smart Transaction Status Page for a pending dapp transaction ([#25965](https://github.com/MetaMask/metamask-extension/pull/25965))
+- fix(multichain): use accounts{Added,Removed} to fetch/clear balances ([#25884](https://github.com/MetaMask/metamask-extension/pull/25884))
+- test: Add integration tests for permit simulation section ([#25856](https://github.com/MetaMask/metamask-extension/pull/25856))
+- fix: fixed max width for permissions page ([#25870](https://github.com/MetaMask/metamask-extension/pull/25870))
+- fix: show current network if domains are undefined ([#25960](https://github.com/MetaMask/metamask-extension/pull/25960))
+- fix: notification slowness and crashes ([#25946](https://github.com/MetaMask/metamask-extension/pull/25946))
+- ci: Disabling non-lint CI on the l10n_crowdin_action branch ([#25809](https://github.com/MetaMask/metamask-extension/pull/25809))
+- refactor: use `withKeyring` method ([#25435](https://github.com/MetaMask/metamask-extension/pull/25435))
+- feat: add BTC support survey link ([#25875](https://github.com/MetaMask/metamask-extension/pull/25875))
+- fix: re-organize files under assets folder ([#25897](https://github.com/MetaMask/metamask-extension/pull/25897))
+- fix: fix css nft detail ([#25931](https://github.com/MetaMask/metamask-extension/pull/25931))
+- fix: Implement Auto-Enable Feature for Basic Functionality in Metamask Extension v12.1.0 ([#25944](https://github.com/MetaMask/metamask-extension/pull/25944))
+- fix: Handle error when offscreen document already exists ([#25138](https://github.com/MetaMask/metamask-extension/pull/25138))
+- test: Expand coverage of sourcemap validator ([#25115](https://github.com/MetaMask/metamask-extension/pull/25115))
+- feat: Add full screen Snap Home and Dialog ([#25670](https://github.com/MetaMask/metamask-extension/pull/25670))
+- chore: swaps codeowners reorg ([#24803](https://github.com/MetaMask/metamask-extension/pull/24803))
+- fix: track token detection enabled ([#25822](https://github.com/MetaMask/metamask-extension/pull/25822))
+- fix: rm locales in other languages ([#25936](https://github.com/MetaMask/metamask-extension/pull/25936))
+- fix: fix ([#25907](https://github.com/MetaMask/metamask-extension/pull/25907))
+- fix: password reset ([#25847](https://github.com/MetaMask/metamask-extension/pull/25847))
+- New Crowdin translations by Github Action ([#24889](https://github.com/MetaMask/metamask-extension/pull/24889))
+- fix: Remove abandoned test:unit:jest command ([#25905](https://github.com/MetaMask/metamask-extension/pull/25905))
+- fix(22851): check if active device to prevent autoconnect for hw ([#25503](https://github.com/MetaMask/metamask-extension/pull/25503))
+- test: Removed step from e2e tests ([#25910](https://github.com/MetaMask/metamask-extension/pull/25910))
+- fix: calcTokenAmount BigNumber more than 15 digits error ([#25799](https://github.com/MetaMask/metamask-extension/pull/25799))
+- feat: add custom form check alerts ([#25259](https://github.com/MetaMask/metamask-extension/pull/25259))
+- fix: test failure on firefox ([#25895](https://github.com/MetaMask/metamask-extension/pull/25895))
+- fix: disables "swap and send" for MMI ([#25886](https://github.com/MetaMask/metamask-extension/pull/25886))
+- fix: Fixed flaky test 24645 ([#25786](https://github.com/MetaMask/metamask-extension/pull/25786))
+- chore: refactor SwapsController so it extends from BaseControllerV2 ([#25681](https://github.com/MetaMask/metamask-extension/pull/25681))
+- feat: Replace "Manage in settings" with "No thanks" in the STX Opt In modal, only show the modal for non-zero balances ([#25848](https://github.com/MetaMask/metamask-extension/pull/25848))
+- feat: Display advanced section within confirmation by default for some users ([#25687](https://github.com/MetaMask/metamask-extension/pull/25687))
+- chore: bump assets-controllers to v36.0.0 ([#25857](https://github.com/MetaMask/metamask-extension/pull/25857))
+- fix: add name to scuttling exception list ([#25849](https://github.com/MetaMask/metamask-extension/pull/25849))
+- fix: update build version to align with firefox's newer version restrictions ([#25456](https://github.com/MetaMask/metamask-extension/pull/25456))
+- feat: regression label ([#25691](https://github.com/MetaMask/metamask-extension/pull/25691))
+- chore: Master sync ([#25816](https://github.com/MetaMask/metamask-extension/pull/25816))
+- fix: contract data in metrics ([#25759](https://github.com/MetaMask/metamask-extension/pull/25759))
+- fix: flaky test `ERC721 NFTs testdapp interaction` ([#25854](https://github.com/MetaMask/metamask-extension/pull/25854))
+- fix: flaky test `Create BTC Account cannot create multiple BTC accounts...` ([#25861](https://github.com/MetaMask/metamask-extension/pull/25861))
+- feat: support creation of Bitcoin testnet accounts ([#25772](https://github.com/MetaMask/metamask-extension/pull/25772))
+- fix: use of an header in a dedicated call ([#25828](https://github.com/MetaMask/metamask-extension/pull/25828))
+- feat(tests): add btc e2e tests ([#25663](https://github.com/MetaMask/metamask-extension/pull/25663))
+- feat: NFT details new design ([#25524](https://github.com/MetaMask/metamask-extension/pull/25524))
+- feat: Add fuzzy matching for name lookup ([#25264](https://github.com/MetaMask/metamask-extension/pull/25264))
+- fix: edit path to dist folder ([#25826](https://github.com/MetaMask/metamask-extension/pull/25826))
+- chore: update @metamask/bitcoin-wallet-snap to 0.2.4 (#25808) ([#25808](https://github.com/MetaMask/metamask-extension/pull/25808))
+- chore: Patch security issue in snaps-utils ([#25827](https://github.com/MetaMask/metamask-extension/pull/25827))
+- feat: add option of copy to info row component ([#25682](https://github.com/MetaMask/metamask-extension/pull/25682))
+- fix: skip blockaid validations for users internal accounts ([#25695](https://github.com/MetaMask/metamask-extension/pull/25695))
+- chore: refactor custody component ([#25684](https://github.com/MetaMask/metamask-extension/pull/25684))
+- Merge origin/develop into master-sync
+- chore: update @metamask/bitcoin-wallet-snap to 0.2.4 ([#25808](https://github.com/MetaMask/metamask-extension/pull/25808))
+- chore: removed unused getCustodianAccountsByAddress method ([#25798](https://github.com/MetaMask/metamask-extension/pull/25798))
+- feat: Make Jest unit tests run faster in GitHub actions ([#25726](https://github.com/MetaMask/metamask-extension/pull/25726))
+- revert: un-revert metrics and signature refactor test ([#25758](https://github.com/MetaMask/metamask-extension/pull/25758))
+- feat: Add `ui_customizations` metric for transactions ([#25736](https://github.com/MetaMask/metamask-extension/pull/25736))
+- test: add e2e tests for navigation (#25652) ([#25652](https://github.com/MetaMask/metamask-extension/pull/25652))
+- chore: remove `BTC_BETA_SUPPORT` flag ([#25776](https://github.com/MetaMask/metamask-extension/pull/25776))
+- chore: update @metamask/bitcoin-wallet-snap to 0.2.3 ([#25775](https://github.com/MetaMask/metamask-extension/pull/25775))
+- feat: add more whitelisted portfolio URLs ([#25767](https://github.com/MetaMask/metamask-extension/pull/25767))
+- fix: Fix page width for fullscreen mode send page ([#25639](https://github.com/MetaMask/metamask-extension/pull/25639))
+- chore: Update Snaps codeowners list ([#25581](https://github.com/MetaMask/metamask-extension/pull/25581))
+- fix: fine-tune for `Delineator` component styles ([#25760](https://github.com/MetaMask/metamask-extension/pull/25760))
+- feat: decode transaction data ([#25597](https://github.com/MetaMask/metamask-extension/pull/25597))
+- feat: add `Delineator` component ([#25610](https://github.com/MetaMask/metamask-extension/pull/25610))
+- feat(ramps): update isNativeTokenBuyable to include BTC ([#25621](https://github.com/MetaMask/metamask-extension/pull/25621))
+- fix: Fix issue 25285 max insufficient funds for gas ([#25574](https://github.com/MetaMask/metamask-extension/pull/25574))
+- feat: add BTC experimental toggle ([#25672](https://github.com/MetaMask/metamask-extension/pull/25672))
+- build: bump gas-fee-controller to v18 and remove patch ([#25679](https://github.com/MetaMask/metamask-extension/pull/25679))
+- fix: show correct asset and balance when BTC account is the selected account ([#25719](https://github.com/MetaMask/metamask-extension/pull/25719))
+- feat(btc): add BTC account creation menu entry ([#25625](https://github.com/MetaMask/metamask-extension/pull/25625))
+- fix: flaky test `Test Snap Metrics test snap update rejected metric` ([#25744](https://github.com/MetaMask/metamask-extension/pull/25744))
+- chore(deps): bump @metamask/accounts-controller from ^17.0.0 to ^17.2.0 ([#25676](https://github.com/MetaMask/metamask-extension/pull/25676))
+- fix: use LAVAMOAT_UPDATE_TOKEN in attributions workflow ([#25731](https://github.com/MetaMask/metamask-extension/pull/25731))
+- fix: caveat mutations for non-EVM accounts ([#25739](https://github.com/MetaMask/metamask-extension/pull/25739))
+- test: Add UI integration tests ([#24428](https://github.com/MetaMask/metamask-extension/pull/24428))
+- fix: revert "test: add e2e tests for navigation (#25652)" ([#25652](https://github.com/MetaMask/metamask-extension/pull/25652))
+- chore: Revert "test: e2e metrics test and refactor" ([#25722](https://github.com/MetaMask/metamask-extension/pull/25722))
+- feat: bundle pre-installed Bitcoin Wallet Snap ([#25715](https://github.com/MetaMask/metamask-extension/pull/25715))
+- fix: protect against phishing domain redirects in main/sub frames for http(s) requests ([#25153](https://github.com/MetaMask/metamask-extension/pull/25153))
+- fix: Fix crash of Transaction screen with smart transaction ([#25717](https://github.com/MetaMask/metamask-extension/pull/25717))
+- fix: Hide MMI Account Mistmatch BannerAlert from Sign-in with Ethereum (SIWE) Redesign Page ([#25662](https://github.com/MetaMask/metamask-extension/pull/25662))
+- fix: flaky test `Create token, approve token and approve token without gas approves an already created token and displays the token approval data` ([#25706](https://github.com/MetaMask/metamask-extension/pull/25706))
+- feat: Enable SIWE Signature Redesign ([#25660](https://github.com/MetaMask/metamask-extension/pull/25660))
+- fix: flaky test `Request-queue UI changes handles three confirmations on three confirmations concurrently` ([#25675](https://github.com/MetaMask/metamask-extension/pull/25675))
+- feat: move unit tests from Circleci to Github actions ([#25570](https://github.com/MetaMask/metamask-extension/pull/25570))
+- test: e2e metrics test and refactor ([#25632](https://github.com/MetaMask/metamask-extension/pull/25632))
+- test: add e2e tests for navigation ([#25652](https://github.com/MetaMask/metamask-extension/pull/25652))
+- feat: support security alerts API ([#25544](https://github.com/MetaMask/metamask-extension/pull/25544))
+- feat(ramps): add flag to ensure ramp networks are only fetched once ([#25686](https://github.com/MetaMask/metamask-extension/pull/25686))
+- fix: allow ramps dev environment on Flask ([#25659](https://github.com/MetaMask/metamask-extension/pull/25659))
+- feat: added check for if the selected account is BTC in transaction-list ([#25642](https://github.com/MetaMask/metamask-extension/pull/25642))
+- feat: Gas Fees Redesign PoC ([#24714](https://github.com/MetaMask/metamask-extension/pull/24714))
+- fix: show connected toast only for EVM accounts ([#25628](https://github.com/MetaMask/metamask-extension/pull/25628))
+- fix: changed logic to use the new banner alert ([#25626](https://github.com/MetaMask/metamask-extension/pull/25626))
+- fix: set network client id for domain ([#25646](https://github.com/MetaMask/metamask-extension/pull/25646))
+- feat: improvement for how we display big and small numbers ([#25438](https://github.com/MetaMask/metamask-extension/pull/25438))
+- chore: restore bot workflow to update attributions ([#25211](https://github.com/MetaMask/metamask-extension/pull/25211))
+- test: add swap e2e tests on Tenderly network ([#25060](https://github.com/MetaMask/metamask-extension/pull/25060))
+- fix: UX: Multichain: Add safeguard to throw error when confirmation chainId doesn't match current chainId ([#25634](https://github.com/MetaMask/metamask-extension/pull/25634))
+- chore: updates MMI custody controller ([#25631](https://github.com/MetaMask/metamask-extension/pull/25631))
+- fix: flaky test `Test Snap Get Locale test snap_getLocale functionality` ([#25648](https://github.com/MetaMask/metamask-extension/pull/25648))
+- fix: Skip blockaid validation for SIWE signature types ([#25612](https://github.com/MetaMask/metamask-extension/pull/25612))
+- feat: Add support for security alerts on zkSync, Berachain, Scroll and Metachain One on extension ([#25555](https://github.com/MetaMask/metamask-extension/pull/25555))
+- fix: Multichain: UX: Check for transactions on all networks and QueuedRequestCount ([#25614](https://github.com/MetaMask/metamask-extension/pull/25614))
+- feat: define which keyring methods Portfolio can call ([#25633](https://github.com/MetaMask/metamask-extension/pull/25633))
+- chore: flaky E2E tests improved ([#25565](https://github.com/MetaMask/metamask-extension/pull/25565))
+- feat: add SIWE mismatch account warning alert ([#25613](https://github.com/MetaMask/metamask-extension/pull/25613))
+- fix: support multichain in blockexplorer and qr code ([#25526](https://github.com/MetaMask/metamask-extension/pull/25526))
+- fix: decimal places displayed on token value on permit pages ([#25410](https://github.com/MetaMask/metamask-extension/pull/25410))
+- feat: added BTC variant to ramps-card and illustration image ([#25615](https://github.com/MetaMask/metamask-extension/pull/25615))
+- fix: Remove unused fixtures and fix test name in smart swaps disabled spec ([#25616](https://github.com/MetaMask/metamask-extension/pull/25616))
+- chore: Update @metamask/smart-transactions-controller from 10.1.2 to 10.1.6 ([#25611](https://github.com/MetaMask/metamask-extension/pull/25611))
+- fix: Fix issue 22837 about unknown error during ledger pair ([#25462](https://github.com/MetaMask/metamask-extension/pull/25462))
+- test: add e2e to swap with snap account ([#25558](https://github.com/MetaMask/metamask-extension/pull/25558))
+- chore: exclude running git diff job for the e2e quality gate in `develop`, `master` and release branches ([#25605](https://github.com/MetaMask/metamask-extension/pull/25605))
+- chore: [Delivery] Update author mapping list for PR ([#25606](https://github.com/MetaMask/metamask-extension/pull/25606))
+- fix: page object selector not found ([#25624](https://github.com/MetaMask/metamask-extension/pull/25624))
+- test: Initial PR for integrating the Page Object Model (POM) into e2e test suite ([#25373](https://github.com/MetaMask/metamask-extension/pull/25373))
+- refactor: Replace deprecated mixins with Text component in selected-account.component.js ([#25262](https://github.com/MetaMask/metamask-extension/pull/25262))
+- refactor: Replace deprecated mixins with Text component in unlock-page.component.js ([#25227](https://github.com/MetaMask/metamask-extension/pull/25227))
+- chore: Create a story for RestoreVaultPage component ([#25284](https://github.com/MetaMask/metamask-extension/pull/25284))
+- fix(snaps): Fix alignment of install origin is `snap-authorship-expanded` ([#25583](https://github.com/MetaMask/metamask-extension/pull/25583))
+- feat: Remove blockaid migration BannerAlert ([#25556](https://github.com/MetaMask/metamask-extension/pull/25556))
+- fix: failingt e2e `Click bridge button from asset page @no-mmi loads portfolio tab when flag is turned off` ([#25607](https://github.com/MetaMask/metamask-extension/pull/25607))
+- chore: adds quality gate for rerunning e2e spec files that are new or have been modified ([#24556](https://github.com/MetaMask/metamask-extension/pull/24556))
+- chore(deps): bump assets controller to v34.0.0 ([#25540](https://github.com/MetaMask/metamask-extension/pull/25540))
+- chore: add bridge controller, store and api utils ([#25044](https://github.com/MetaMask/metamask-extension/pull/25044))
+- fix: add eth_signTypedData and eth_signTypedData_v3 to `methodsRequiringNetworkSwitch` ([#25562](https://github.com/MetaMask/metamask-extension/pull/25562))
+
## [12.2.0]
## [12.1.3]
@@ -5016,7 +5374,8 @@ Update styles and spacing on the critical error page ([#20350](https://github.c
- Added the ability to restore accounts from seed words.
-[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v12.2.0...HEAD
+[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v12.3.0...HEAD
+[12.3.0]: https://github.com/MetaMask/metamask-extension/compare/v12.2.0...v12.3.0
[12.2.0]: https://github.com/MetaMask/metamask-extension/compare/v12.1.3...v12.2.0
[12.1.3]: https://github.com/MetaMask/metamask-extension/compare/v12.1.2...v12.1.3
[12.1.2]: https://github.com/MetaMask/metamask-extension/compare/v12.1.1...v12.1.2
diff --git a/package.json b/package.json
index 0176477d1e4e..251e90199db9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "metamask-crx",
- "version": "12.2.0",
+ "version": "12.3.0",
"private": true,
"repository": {
"type": "git",
From 06c25bb1509cf9551fb8322baa05b1baeb88a45c Mon Sep 17 00:00:00 2001
From: Dan J Miller
Date: Fri, 6 Sep 2024 16:47:08 -0230
Subject: [PATCH 02/43] Lint fix
---
app/scripts/controllers/swaps/swaps.test.ts | 1 -
app/scripts/lib/ppom/ppom-middleware.test.ts | 2 +-
.../lib/snap-keyring/snap-keyring.test.ts | 4 ++++
app/scripts/lib/transaction/util.test.ts | 24 +++++++++++++++----
package.json | 1 -
shared/modules/metametrics.test.ts | 1 +
shared/modules/mv3.utils.js | 5 ++--
shared/modules/selectors/index.ts | 2 --
.../modules/selectors/smart-transactions.ts | 5 +---
ui/selectors/accounts.test.ts | 13 ++++++----
ui/store/actions.ts | 4 ++++
11 files changed, 41 insertions(+), 21 deletions(-)
diff --git a/app/scripts/controllers/swaps/swaps.test.ts b/app/scripts/controllers/swaps/swaps.test.ts
index 62cc6796160f..8b2fbd22d032 100644
--- a/app/scripts/controllers/swaps/swaps.test.ts
+++ b/app/scripts/controllers/swaps/swaps.test.ts
@@ -1182,7 +1182,6 @@ describe('SwapsController', function () {
swapsQuotePrefetchingRefreshTime,
swapsStxBatchStatusRefreshTime,
swapsStxGetTransactionsRefreshTime,
- swapsStxStatusDeadline,
},
});
diff --git a/app/scripts/lib/ppom/ppom-middleware.test.ts b/app/scripts/lib/ppom/ppom-middleware.test.ts
index a9df5e093f95..6aafcddd0e58 100644
--- a/app/scripts/lib/ppom/ppom-middleware.test.ts
+++ b/app/scripts/lib/ppom/ppom-middleware.test.ts
@@ -222,7 +222,7 @@ describe('PPOMMiddleware', () => {
const middlewareFunction = createMiddleware();
const req = {
- ...JsonRpcRequestStruct,
+ ...REQUEST_MOCK,
params: [{ to: INTERNAL_ACCOUNT_ADDRESS }],
method: 'eth_sendTransaction',
securityAlertResponse: undefined,
diff --git a/app/scripts/lib/snap-keyring/snap-keyring.test.ts b/app/scripts/lib/snap-keyring/snap-keyring.test.ts
index bfa8e124d3f0..4136fd1fd1fc 100644
--- a/app/scripts/lib/snap-keyring/snap-keyring.test.ts
+++ b/app/scripts/lib/snap-keyring/snap-keyring.test.ts
@@ -50,6 +50,10 @@ const mockInternalAccount = {
name: mockSnapName,
},
name: accountNameSuggestion,
+ keyring: {
+ type: '',
+ },
+ importTime: 0,
},
};
diff --git a/app/scripts/lib/transaction/util.test.ts b/app/scripts/lib/transaction/util.test.ts
index d4376cb34947..a27844f53b41 100644
--- a/app/scripts/lib/transaction/util.test.ts
+++ b/app/scripts/lib/transaction/util.test.ts
@@ -1,4 +1,4 @@
-import { InternalAccount } from '@metamask/keyring-api';
+import { EthAccountType, InternalAccount } from '@metamask/keyring-api';
import { TransactionParams } from '@metamask/eth-json-rpc-middleware';
import {
TransactionController,
@@ -41,6 +41,24 @@ const SECURITY_ALERT_ID_MOCK = '123';
const INTERNAL_ACCOUNT_ADDRESS = '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b';
+const mockAccount = {
+ type: EthAccountType.Eoa,
+ id: '3afa663e-0600-4d93-868a-61c2e553013b',
+ address: INTERNAL_ACCOUNT_ADDRESS,
+ methods: [],
+ options: {},
+};
+const mockInternalAccount = {
+ ...mockAccount,
+ metadata: {
+ name: `Account 1`,
+ importTime: Date.now(),
+ keyring: {
+ type: '',
+ },
+ },
+};
+
const TRANSACTION_PARAMS_MOCK: TransactionParams = {
from: '0x1',
};
@@ -484,9 +502,7 @@ describe('Transaction Utils', () => {
...sendRequest,
securityAlertsEnabled: false,
chainId: '0x1',
- internalAccounts: {
- address: INTERNAL_ACCOUNT_ADDRESS,
- } as InternalAccount,
+ internalAccounts: [mockInternalAccount],
});
expect(
diff --git a/package.json b/package.json
index 251e90199db9..be00bf7c6c65 100644
--- a/package.json
+++ b/package.json
@@ -264,7 +264,6 @@
"@metamask/snaps-controllers@npm:^8.1.1": "patch:@metamask/snaps-controllers@npm%3A9.4.0#~/.yarn/patches/@metamask-snaps-controllers-npm-9.4.0-7c3abbbea6.patch",
"@metamask/snaps-controllers@npm:^9.4.0": "patch:@metamask/snaps-controllers@npm%3A9.4.0#~/.yarn/patches/@metamask-snaps-controllers-npm-9.4.0-7c3abbbea6.patch",
"@metamask/nonce-tracker@npm:^5.0.0": "patch:@metamask/nonce-tracker@npm%3A5.0.0#~/.yarn/patches/@metamask-nonce-tracker-npm-5.0.0-d81478218e.patch",
- "@metamask/keyring-controller@npm:^16.0.0": "patch:@metamask/keyring-controller@npm%3A17.1.1#~/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch",
"@metamask/keyring-controller@npm:^17.1.0": "patch:@metamask/keyring-controller@npm%3A17.1.1#~/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch",
"@trezor/connect-web@npm:^9.1.11": "patch:@trezor/connect-web@npm%3A9.3.0#~/.yarn/patches/@trezor-connect-web-npm-9.3.0-040ab10d9a.patch"
},
diff --git a/shared/modules/metametrics.test.ts b/shared/modules/metametrics.test.ts
index 29434cfb1687..b313673056ac 100644
--- a/shared/modules/metametrics.test.ts
+++ b/shared/modules/metametrics.test.ts
@@ -43,6 +43,7 @@ const createTransactionMetricsRequest = (customProps = {}) => {
getMethodData: jest.fn(),
getIsRedesignedConfirmationsDeveloperEnabled: jest.fn(),
getIsConfirmationAdvancedDetailsOpen: jest.fn(),
+ getRedesignedConfirmationsEnabled: jest.fn(),
...customProps,
} as TransactionMetricsRequest;
};
diff --git a/shared/modules/mv3.utils.js b/shared/modules/mv3.utils.js
index d2b2cac26ada..417484c46de6 100644
--- a/shared/modules/mv3.utils.js
+++ b/shared/modules/mv3.utils.js
@@ -10,7 +10,7 @@ const runtimeManifest =
* unavailable. That's why we have a fallback using the ENABLE_MV3 constant. The fallback is also
* used in unit tests.
*/
-export const isManifestV3 = runtimeManifest
+const isManifestV3 = runtimeManifest
? runtimeManifest.manifest_version === 3
: // Our build system sets this as a boolean, but in a Node.js context (e.g. unit tests) it will
// always be a string
@@ -31,8 +31,7 @@ const isOffscreenAvailable = Boolean(global.chrome?.offscreen);
* happen to users on MetaMask versions 11.16.7 and higher, who are using a
* chromium browser with a version below 109.
*/
-export const isMv3ButOffscreenDocIsMissing =
- isManifestV3 && !isOffscreenAvailable;
+const isMv3ButOffscreenDocIsMissing = isManifestV3 && !isOffscreenAvailable;
module.exports = {
isManifestV3,
diff --git a/shared/modules/selectors/index.ts b/shared/modules/selectors/index.ts
index 4328f98656b3..d53296394c26 100644
--- a/shared/modules/selectors/index.ts
+++ b/shared/modules/selectors/index.ts
@@ -2,8 +2,6 @@ import { getHardwareWalletType } from '../../../ui/selectors/selectors';
export * from './smart-transactions';
export * from './feature-flags';
-export * from './token-auto-detect';
-export * from './nft-auto-detect';
export * from './account';
export { getHardwareWalletType };
diff --git a/shared/modules/selectors/smart-transactions.ts b/shared/modules/selectors/smart-transactions.ts
index f9256fc334b2..c510e817dbdb 100644
--- a/shared/modules/selectors/smart-transactions.ts
+++ b/shared/modules/selectors/smart-transactions.ts
@@ -10,10 +10,7 @@ import {
getSelectedAccount,
} from '../../../ui/selectors/selectors'; // TODO: Migrate shared selectors to this file.
import { isProduction } from '../environment';
-import {
- MultichainState,
- MultichainState,
-} from '../../../ui/selectors/multichain';
+import { MultichainState } from '../../../ui/selectors/multichain';
type SmartTransactionsMetaMaskState = {
metamask: {
diff --git a/ui/selectors/accounts.test.ts b/ui/selectors/accounts.test.ts
index 76b9ea955862..22fd6f610b12 100644
--- a/ui/selectors/accounts.test.ts
+++ b/ui/selectors/accounts.test.ts
@@ -156,10 +156,11 @@ describe('Accounts Selectors', () => {
...MOCK_STATE.metamask,
internalAccounts: {
selectedAccount: MOCK_ACCOUNT_BIP122_P2WPKH.id,
- accounts: [
- MOCK_ACCOUNT_BIP122_P2WPKH,
- MOCK_ACCOUNT_BIP122_P2WPKH_TESTNET,
- ],
+ accounts: {
+ mock_account_bip122_pwpkh: MOCK_ACCOUNT_BIP122_P2WPKH,
+ mock_account_bip122_p2wpkh_testnet:
+ MOCK_ACCOUNT_BIP122_P2WPKH_TESTNET,
+ },
},
},
};
@@ -174,7 +175,9 @@ describe('Accounts Selectors', () => {
...MOCK_STATE.metamask,
internalAccounts: {
selectedAccount: MOCK_ACCOUNT_BIP122_P2WPKH.id,
- accounts: [MOCK_ACCOUNT_BIP122_P2WPKH],
+ accounts: {
+ mock_account_bip122_p2wpkh: MOCK_ACCOUNT_BIP122_P2WPKH,
+ },
},
},
};
diff --git a/ui/store/actions.ts b/ui/store/actions.ts
index b9b9d362c417..12a54e84c943 100644
--- a/ui/store/actions.ts
+++ b/ui/store/actions.ts
@@ -5549,6 +5549,10 @@ export function setIsProfileSyncingEnabled(
};
}
+export function setConfirmationAdvancedDetailsOpen(value: boolean) {
+ return setPreference('showConfirmationAdvancedDetails', value);
+}
+
export async function getNextAvailableAccountName(
keyring?: KeyringTypes,
): Promise {
From 84e5bb225e5213fc3a6e402a1b4b3215e3e1669e Mon Sep 17 00:00:00 2001
From: Dan J Miller
Date: Mon, 9 Sep 2024 12:26:12 -0230
Subject: [PATCH 03/43] Fix unit tests
---
.../info/row/__snapshots__/row.test.tsx.snap | 4 +-
.../row/__snapshots__/dataTree.test.tsx.snap | 34 +++----------
.../__snapshots__/confirm.test.tsx.snap | 50 +++++++++----------
ui/pages/routes/routes.component.js | 3 ++
.../developer-options-tab.test.tsx.snap | 8 ++-
.../developer-options-tab.tsx | 14 +++---
6 files changed, 49 insertions(+), 64 deletions(-)
diff --git a/ui/components/app/confirm/info/row/__snapshots__/row.test.tsx.snap b/ui/components/app/confirm/info/row/__snapshots__/row.test.tsx.snap
index dffd29798bbc..3d8affc5a90d 100644
--- a/ui/components/app/confirm/info/row/__snapshots__/row.test.tsx.snap
+++ b/ui/components/app/confirm/info/row/__snapshots__/row.test.tsx.snap
@@ -7,7 +7,7 @@ exports[`ConfirmInfoRow should match snapshot 1`] = `
style="overflow-wrap: anywhere; min-height: 24px; position: relative;"
>
-
{
setHideNftEnablementToast(false);
};
+ if (!this.onHomeScreen()) {
+ return null;
+ }
return (
diff --git a/ui/pages/settings/developer-options-tab/__snapshots__/developer-options-tab.test.tsx.snap b/ui/pages/settings/developer-options-tab/__snapshots__/developer-options-tab.test.tsx.snap
index 973e02da7b2e..f7f9b38a0235 100644
--- a/ui/pages/settings/developer-options-tab/__snapshots__/developer-options-tab.test.tsx.snap
+++ b/ui/pages/settings/developer-options-tab/__snapshots__/developer-options-tab.test.tsx.snap
@@ -326,11 +326,13 @@ exports[`Develop options tab should match snapshot 1`] = `
class="settings-page__content-description"
>
+
Generate an unhandled
TestError
in this window.
+
@@ -368,11 +370,13 @@ exports[`Develop options tab should match snapshot 1`] = `
class="settings-page__content-description"
>
+
Generate an unhandled
TestError
in the service worker.
+
@@ -410,11 +414,13 @@ exports[`Develop options tab should match snapshot 1`] = `
class="settings-page__content-description"
>
- Generate a
+
+ Generate a
Developer Test
Sentry trace.
+
diff --git a/ui/pages/settings/developer-options-tab/developer-options-tab.tsx b/ui/pages/settings/developer-options-tab/developer-options-tab.tsx
index efbc6ea6c1da..da1bd4685a75 100644
--- a/ui/pages/settings/developer-options-tab/developer-options-tab.tsx
+++ b/ui/pages/settings/developer-options-tab/developer-options-tab.tsx
@@ -218,8 +218,8 @@ const DeveloperOptionsTab = () => {
const renderServiceWorkerKeepAliveToggle = () => {
return (
handleToggleServiceWorkerAlive(!value)}
dataTestId="developer-options-service-worker-alive-toggle"
@@ -231,8 +231,8 @@ const DeveloperOptionsTab = () => {
const renderNetworkMenuRedesign = () => {
return (
{
setEnableNetworkRedesign(!value);
@@ -249,10 +249,8 @@ const DeveloperOptionsTab = () => {
const renderEnableConfirmationsRedesignToggle = () => {
return (
setEnableConfirmationsRedesignEnabled(!value)
From 06000067adb1f6847dbce2eb2c02843b78531feb Mon Sep 17 00:00:00 2001
From: Dan J Miller
Date: Mon, 9 Sep 2024 13:13:36 -0230
Subject: [PATCH 04/43] Locales lint: remove unused locales
---
app/_locales/de/messages.json | 36 --------------------------------
app/_locales/el/messages.json | 36 --------------------------------
app/_locales/en/messages.json | 30 --------------------------
app/_locales/es/messages.json | 36 --------------------------------
app/_locales/fr/messages.json | 36 --------------------------------
app/_locales/hi/messages.json | 36 --------------------------------
app/_locales/id/messages.json | 36 --------------------------------
app/_locales/ja/messages.json | 36 --------------------------------
app/_locales/ko/messages.json | 36 --------------------------------
app/_locales/pt/messages.json | 36 --------------------------------
app/_locales/ru/messages.json | 36 --------------------------------
app/_locales/tl/messages.json | 36 --------------------------------
app/_locales/tr/messages.json | 36 --------------------------------
app/_locales/vi/messages.json | 36 --------------------------------
app/_locales/zh_CN/messages.json | 36 --------------------------------
15 files changed, 534 deletions(-)
diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json
index 084f184254d7..cdc7fdd96669 100644
--- a/app/_locales/de/messages.json
+++ b/app/_locales/de/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "Genehmigen"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "Erlauben Sie MetaMask, Ihre NFTs mit automatischer Erkennung zu identifizieren und anzuzeigen. Das können Sie tun:"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "Erlauben Sie MetaMask, Ihre Token mit automatischer Erkennung zu entdecken und anzuzeigen. Das können Sie tun:"
- },
"allowMmiToConnectToCustodian": {
"message": "Dadurch kann MMI sich zum Importieren Ihrer Konten mit $1 verbinden."
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "Durch die Anzeige von NFT-Medien und -Daten wird Ihre IP-Adresse an OpenSea oder andere Dritte weitergegeben. Dies kann es Angreifern ermöglichen, Ihre IP-Adresse mit Ihrer Ethereum-Adresse in Verbindung zu bringen. Die automatische NFT-Erkennung basiert auf dieser Einstellung und ist nicht verfügbar, wenn diese ausgeschaltet ist."
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "Verwenden Sie Ihre NFTs sofort"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "Verwenden Sie Ihre Tokens sofort"
- },
"doNotShare": {
"message": "Teilen Sie dies mit niemanden"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "Beschleunigung der Gasgebühr bearbeiten"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "Mühelose Navigation durch Ihre digitalen Assets"
- },
"enable": {
"message": "Aktivieren"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " In den Einstellungen aktivieren."
},
- "enableNftAutoDetection": {
- "message": "Automatische NFT-Erkennung aktivieren"
- },
"enableSnap": {
"message": "Aktivieren"
},
@@ -1765,12 +1747,6 @@
"message": "$1 aktivieren",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "Automatische Token-Erkennung aktivieren"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "Bei Nutzern, deren Basisfunktionalität aktiviert ist, wird diese automatisch in der Metamask-Erweiterung v12.3.0 aktiviert"
- },
"enabled": {
"message": "Aktiviert"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "Sofortiger Zugriff auf Ihre NFTs"
- },
- "immediateAccessToYourTokens": {
- "message": "Sofortiger Zugriff auf Ihre Tokens"
- },
"import": {
"message": "Importieren",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "Nicht genügend Gas"
},
- "notRightNow": {
- "message": "Im Moment nicht"
- },
"note": {
"message": "Notiz"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "Wenn wir Metriken sammeln, wird es immer wie folgt sein ..."
},
- "onboardingMetametricsDisagree": {
- "message": "Nein, danke!"
- },
"onboardingMetametricsInfuraTerms": {
"message": "Wir werden Sie informieren, wenn wir beschließen, diese Daten für andere Zwecke zu verwenden. Für weitere Informationen können Sie unsere $1 einsehen. Vergessen Sie nicht, dass Sie jederzeit zu Einstellungen gehen und sich abmelden können.",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json
index 5298c61a533b..3db88285098a 100644
--- a/app/_locales/el/messages.json
+++ b/app/_locales/el/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "Να επιτρέπεται"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "Επιτρέψτε στο MetaMask να ανιχνεύει και να εμφανίζει τα NFT σας με αυτόματο εντοπισμό. Θα μπορείτε να:"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "Επιτρέψτε στο MetaMask να ανιχνεύει και να εμφανίζει τα tokens σας με αυτόματο εντοπισμό. Θα μπορείτε να:"
- },
"allowMmiToConnectToCustodian": {
"message": "Αυτό θα επιτρέψει στο MMI να συνδεθεί στο $1 για να εισαγάγει τους λογαριασμούς σας."
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "Η προβολή μέσων και δεδομένων NFT εκθέτει τη διεύθυνση IP σας στo OpenSea ή σε άλλους τρίτους. Αυτό μπορεί να επιτρέψει στους εισβολείς να συσχετίσουν τη διεύθυνση IP σας με τη διεύθυνση σας στο Ethereum. Η αυτόματη ανίχνευση NFT βασίζεται σε αυτή τη ρύθμιση και δεν θα είναι διαθέσιμη όταν είναι απενεργοποιημένη."
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "Ενημερωθείτε για τη χρήση των NFT σας"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "Ενημερωθείτε για τη χρήση των tokens σας"
- },
"doNotShare": {
"message": "Μην το μοιραστείτε με κανέναν"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "Επεξεργασία τελών επίσπευσης συναλλαγής"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "Εύκολη περιήγηση στα ψηφιακά σας περιουσιακά στοιχεία"
- },
"enable": {
"message": "Ενεργοποίηση"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": "Ενεργοποιήστε το από τις Ρυθμίσεις."
},
- "enableNftAutoDetection": {
- "message": "Ενεργοποίηση της αυτόματης ανίχνευσης NFT"
- },
"enableSnap": {
"message": "Ενεργοποίηση"
},
@@ -1765,12 +1747,6 @@
"message": "ενεργοποίηση $1",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "Ενεργοποίηση της αυτόματης ανίχνευσης των tokens"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "Οι χρήστες με ενεργοποιημένη την επιλογή Βασικές Λειτουργίες θα την έχουν ενεργοποιήσει αυτόματα στην επέκταση του Metamask v12.3.0"
- },
"enabled": {
"message": "Ενεργοποιημένο"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "Άμεση πρόσβαση στα NFT σας"
- },
- "immediateAccessToYourTokens": {
- "message": "Άμεση πρόσβαση στα tokens σας"
- },
"import": {
"message": "Εισαγωγή",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "Δεν υπάρχει αρκετό τέλος συναλλαγής"
},
- "notRightNow": {
- "message": "Όχι τώρα"
- },
"note": {
"message": "Σημείωση"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "Όταν συγκεντρώνουμε μετρήσεις, θα είναι πάντα..."
},
- "onboardingMetametricsDisagree": {
- "message": "Όχι, ευχαριστώ"
- },
"onboardingMetametricsInfuraTerms": {
"message": "Θα σας ενημερώσουμε εάν αποφασίσουμε να χρησιμοποιήσουμε αυτά τα δεδομένα για άλλους σκοπούς. Για περισσότερες πληροφορίες, μπορείτε να ανατρέξετε στην $1. Να θυμάστε ότι μπορείτε να μεταβείτε στις ρυθμίσεις και να εξαιρεθείτε ανά πάσα στιγμή.",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index 7a2abeb2e391..c3683becebbd 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -1549,24 +1549,6 @@
"developerOptions": {
"message": "Developer Options"
},
- "developerOptionsEnableConfirmationsRedesignDescription": {
- "message": "Enables or disables the confirmations redesign feature currently in development"
- },
- "developerOptionsEnableConfirmationsRedesignTitle": {
- "message": "Confirmations Redesign"
- },
- "developerOptionsNetworkMenuRedesignDescription": {
- "message": "Toggles the new design of the Networks menu"
- },
- "developerOptionsNetworkMenuRedesignTitle": {
- "message": "Network Menu Redesign"
- },
- "developerOptionsResetStatesAnnouncementsDescription": {
- "message": "Resets isShown boolean to false for all announcements. Announcements are the notifications shown in the What's New popup modal."
- },
- "developerOptionsResetStatesOnboarding": {
- "message": "Resets various states related to onboarding and redirects to the \"Secure Your Wallet\" onboarding page."
- },
"developerOptionsSentryButtonGenerateBackgroundError": {
"message": "Generate Background Error"
},
@@ -1585,9 +1567,6 @@
"developerOptionsSentryDescriptionGenerateUIError": {
"message": "Generate an unhandled $1 in this window."
},
- "developerOptionsServiceWorkerKeepAlive": {
- "message": "Results in a timestamp being continuously saved to session.storage"
- },
"disabledGasOptionToolTipMessage": {
"message": "“$1” is disabled because it does not meet the minimum of a 10% increase from the original gas fee.",
"description": "$1 is gas estimate type which can be market or aggressive"
@@ -1795,12 +1774,6 @@
"message": "enable $1",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "Enable token autodetection"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "Users with the Basic Functionality toggle on will have this automatically turned on in the Metamask Extension v12.3.0"
- },
"enabled": {
"message": "Enabled"
},
@@ -3562,9 +3535,6 @@
"onboardingMetametricsDescription2": {
"message": "When we gather metrics, it will always be..."
},
- "onboardingMetametricsDisagree": {
- "message": "No thanks"
- },
"onboardingMetametricsInfuraTerms": {
"message": "We’ll let you know if we decide to use this data for other purposes. You can review our $1 for more information. Remember, you can go to settings and opt out at any time.",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json
index 0b18d79e33cf..19031ace0ed8 100644
--- a/app/_locales/es/messages.json
+++ b/app/_locales/es/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "Permitir"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "Permita que MetaMask detecte y muestre sus NFT con autodetección. Podrá:"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "Permita que MetaMask detecte y muestre sus tokens con autodetección. Podrá:"
- },
"allowMmiToConnectToCustodian": {
"message": "Esto permitirá que MMI se conecte a $1 para importar sus cuentas."
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "Mostrar los medios y datos NFT expone su dirección IP a OpenSea u otros terceros. Esto puede permitir que los atacantes asocien su dirección IP con su dirección Ethereum. La detección automática de NFT se basa en esta configuración y no estará disponible cuando esté desactivada."
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "Comience a utilizar sus NFT"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "Comience a utilizar sus tokens"
- },
"doNotShare": {
"message": "No comparta esto con nadie"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "Editar la tarifa de aceleración de gas"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "Navegue sin esfuerzo por sus activos digitales"
- },
"enable": {
"message": "Habilitar"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " Actívela en Configuración."
},
- "enableNftAutoDetection": {
- "message": "Habilite la autodetección de NFT"
- },
"enableSnap": {
"message": "Activar"
},
@@ -1765,12 +1747,6 @@
"message": "activar $1",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "Activar la autodetección de tokens"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "Esta opción estará activada automáticamente en la extensión Metamask v12.3.0 para los usuarios que tengan activada la funcionalidad básica"
- },
"enabled": {
"message": "Activado"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "Acceda inmediatamente a sus NFT"
- },
- "immediateAccessToYourTokens": {
- "message": "Acceso inmediato a sus tokens"
- },
"import": {
"message": "Importar",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "No hay gas suficiente"
},
- "notRightNow": {
- "message": "Ahora no"
- },
"note": {
"message": "Nota"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "Al recopilar métricas, siempre será..."
},
- "onboardingMetametricsDisagree": {
- "message": "No, gracias"
- },
"onboardingMetametricsInfuraTerms": {
"message": "Le informaremos si decidimos usar estos datos para otros fines. Puede consultar $1 para obtener más información. Recuerde que puede acceder a la configuración y excluirse en cualquier momento.",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json
index ec3a338656e3..2e7d3697e11d 100644
--- a/app/_locales/fr/messages.json
+++ b/app/_locales/fr/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "Autoriser"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "Autorisez MetaMask à détecter et à afficher vos NFT grâce à la détection automatique des NFT. Vous pourrez ainsi :"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "Autorisez MetaMask à détecter et à afficher vos jetons grâce à la détection automatique des jetons. Vous pourrez ainsi :"
- },
"allowMmiToConnectToCustodian": {
"message": "Cela permettra à MMI de se connecter à $1 pour importer vos comptes."
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "L’affichage des médias et des données NFT expose votre adresse IP à OpenSea ou à d’autres fournisseurs de services tiers. Cela permet à des hackers d’associer votre adresse IP à votre adresse Ethereum. La détection automatique des NFT dépend de ce paramètre et ne sera pas disponible lorsque celui-ci est désactivé."
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "Commencer à utiliser vos NFT"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "Commencez à utiliser vos jetons"
- },
"doNotShare": {
"message": "Ne partagez ceci avec personne"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "Modifier les gas fees d’accélération"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "Gérez facilement à vos actifs numériques"
- },
"enable": {
"message": "Activer"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " Activez-la depuis les Paramètres."
},
- "enableNftAutoDetection": {
- "message": "Activer la détection automatique des NFT"
- },
"enableSnap": {
"message": "Activer"
},
@@ -1765,12 +1747,6 @@
"message": "activer $1",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "Activer la détection automatique des jetons"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "Cette option sera automatiquement activée dans l’extension Metamask v12.3.0 si l’option « Fonctionnalité de base » est déjà activée"
- },
"enabled": {
"message": "Activé"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "Accéder immédiatement à vos NFT"
- },
- "immediateAccessToYourTokens": {
- "message": "Accès immédiat à vos jetons"
- },
"import": {
"message": "Importer",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "Pas assez de gaz"
},
- "notRightNow": {
- "message": "Pas maintenant"
- },
"note": {
"message": "Note"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "Lorsque nous recueillons des données, elles sont toujours…"
},
- "onboardingMetametricsDisagree": {
- "message": "Non merci"
- },
"onboardingMetametricsInfuraTerms": {
"message": "Nous vous informerons si nous décidons d’utiliser ces données à d’autres fins. Pour plus d’informations, vous pouvez consulter notre $1. N’oubliez pas que vous pouvez aller dans les paramètres et vous désinscrire à tout moment.",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json
index 8b941ba8716d..1c1e9363d761 100644
--- a/app/_locales/hi/messages.json
+++ b/app/_locales/hi/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "अनुमति दें"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "MetaMask को ऑटोडिटेक्शन के साथ आपके NFT का पता लगाने और प्रदर्शित करने की अनुमति दें। आप यह कर सकेंगे:"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "MetaMask को ऑटोडिटेक्शन के साथ आपके टोकन का पता लगाने और प्रदर्शित करने की अनुमति दें। आप यह कर सकेंगे:"
- },
"allowMmiToConnectToCustodian": {
"message": "यह आपके एकाउंट्स को इम्पोर्ट करने के लिए MMI को $1 से कनेक्ट करने की अनुमति देगा।"
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "NFT मीडिया और डेटा दिखाने से आपका IP एड्रेस OpenSea या अन्य थर्ड पार्टियों के सामने आ जाता है। ऐसा होने पर, हमला करने वाले आपके IP एड्रेस को आपके Ethereum एड्रेस के साथ जोड़ पाते हैं। NFT ऑटोडिटेक्शन की सुविधा इस सेटिंग पर निर्भर करती है, और इस सेटिंग को बंद किए जाने पर उपलब्ध नहीं रहेगी।"
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "अपने NFT का उपयोग करने के लिए सीधे प्रवेश करें"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "अपने टोकन का उपयोग करने के लिए सीधे प्रवेश करें"
- },
"doNotShare": {
"message": "इसे किसी के साथ शेयर न करें।"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "गैस फ़ीस स्पीड अप को बदलें"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "अपनी डिजिटल एसेट को आसानी से नेविगेट करें"
- },
"enable": {
"message": "चालू करें"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " इसे सेटिंग्स से इनेबल करें।"
},
- "enableNftAutoDetection": {
- "message": "NFT ऑटोडिटेक्शन चालू करें"
- },
"enableSnap": {
"message": "इनेबल करें"
},
@@ -1765,12 +1747,6 @@
"message": "$1 इनेबल करें",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "टोकन ऑटोडिटेक्शन चालू करें"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "बेसिक फ़ंक्शनैलिटी टॉगल को चालू रखने वाले उपयोगकर्ताओं के लिए MetaMask एक्सटेंशन v12.3.0 में यह स्वचालित रूप से चालू हो जाएगा"
- },
"enabled": {
"message": "इनेबल किया गया"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "तुरंत अपने NFT तक पहुंचें"
- },
- "immediateAccessToYourTokens": {
- "message": "आपके टोकन तक तत्काल पहुंच"
- },
"import": {
"message": "इम्पोर्ट करें",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "गैस कम है"
},
- "notRightNow": {
- "message": "अभी नहीं"
- },
"note": {
"message": "टिप्पणी"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "जब हम मेट्रिक्स इकट्ठा करते हैं, तो यह हमेशा... रहेगा"
},
- "onboardingMetametricsDisagree": {
- "message": "जी नहीं, धन्यवाद"
- },
"onboardingMetametricsInfuraTerms": {
"message": "यदि हम इस डेटा का उपयोग अन्य उद्देश्यों के लिए करने का निर्णय लेते हैं तो हम आपको बताएंगे। अधिक जानकारी के लिए आप हमारे $1 की समीक्षा कर सकते हैं। याद रखें, आप किसी भी समय सेटिंग्स में जाकर ऑप्ट आउट कर सकते हैं।",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json
index 6d58c18e01b4..13e7c6d1cbec 100644
--- a/app/_locales/id/messages.json
+++ b/app/_locales/id/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "Izinkan"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "Izinkan MetaMask mendeteksi dan menampilkan NFT dengan autodeteksi. Anda dapat:"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "Izinkan MetaMask mendeteksi dan menampilkan token dengan autodeteksi. Anda dapat:"
- },
"allowMmiToConnectToCustodian": {
"message": "Ini akan memungkinkan MMI terhubung ke $1 untuk mengimpor akun Anda."
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "Alamat IP dapat diketahui oleh OpenSea atau pihak ketiga lainnya saat menampilkan media dan data NFT. Ini memungkinkan penyerang menghubungkan alamat IP dengan alamat Ethereum Anda. Deteksi otomatis NFT bergantung pada pengaturan ini, dan tidak akan tersedia saat dinonaktifkan."
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "Gunakan NFT secara langsung"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "Gunakan token secara langsung"
- },
"doNotShare": {
"message": "Jangan bagikan ini kepada siapa pun"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "Edit biaya gas percepatan"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "Navigasikan aset digital Anda dengan mudah"
- },
"enable": {
"message": "Aktifkan"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " Aktifkan dari Pengaturan."
},
- "enableNftAutoDetection": {
- "message": "Aktifkan autodeteksi NFT"
- },
"enableSnap": {
"message": "Aktifkan"
},
@@ -1765,12 +1747,6 @@
"message": "aktifkan $1",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "Aktifkan autodeteksi token"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "Pengguna dengan Fungsionalitas Dasar yang diaktifkan akan mengaktifkannya secara otomatis di Ekstensi MetaMask v12.3.0"
- },
"enabled": {
"message": "Diaktifkan"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "Akses NFT secara langsung"
- },
- "immediateAccessToYourTokens": {
- "message": "Akses langsung ke token Anda"
- },
"import": {
"message": "Impor",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "Gas tidak cukup"
},
- "notRightNow": {
- "message": "Tidak sekarang"
- },
"note": {
"message": "Catatan"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "Saat kami mengumpulkan metrik, maka akan selalu..."
},
- "onboardingMetametricsDisagree": {
- "message": "Tidak, terima kasih"
- },
"onboardingMetametricsInfuraTerms": {
"message": "Kami akan memberitahukan keputusan untuk menggunakan data ini dengan tujuan lain. Anda dapat meninjau $1 kami untuk informasi selengkapnya. Ingat, Anda dapat membuka pengaturan dan memilih keluar setiap saat.",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json
index 754e883d4c25..5935c29f4eab 100644
--- a/app/_locales/ja/messages.json
+++ b/app/_locales/ja/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "許可する"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "MetaMaskによる自動検出でのNFTの検出と表示を許可してください。これにより、次のことが可能になります:"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "MetaMaskによる自動検出でのトークンの検出と表示を許可してください。これにより、次のことが可能になります:"
- },
"allowMmiToConnectToCustodian": {
"message": "これにより、MMIが$1に接続してアカウントをインポートできるようになります。"
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "NFTのメディアとデータを表示した場合、IPアドレスがOpenSeaをはじめとするサードパーティに公開されます。その結果、攻撃者がユーザーのIPアドレスとイーサリアムアドレスを関連付けられるようになる可能性があります。NFTの自動検出はこの設定に依存しており、この設定を無効にすると利用できなくなります。"
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "NFTをすぐに使用開始"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "トークンをすぐに使用開始"
- },
"doNotShare": {
"message": "これは誰にも教えないでください"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "高速化用のガス代を編集"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "デジタル資産を簡単に運用"
- },
"enable": {
"message": "有効にする"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " 設定で有効にします。"
},
- "enableNftAutoDetection": {
- "message": "NFTの自動検出を有効にする"
- },
"enableSnap": {
"message": "有効にする"
},
@@ -1765,12 +1747,6 @@
"message": "$1を有効にする",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "トークンの自動検出を有効にする"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "基本機能トグルがオンになっているユーザーは、MetaMask拡張機能 v12.3.0で、この機能が自動的にオンになります。"
- },
"enabled": {
"message": "有効"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "NFTにすぐにアクセス"
- },
- "immediateAccessToYourTokens": {
- "message": "トークンにすぐにアクセス"
- },
"import": {
"message": "インポート",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "ガスが不足しています"
},
- "notRightNow": {
- "message": "また後で"
- },
"note": {
"message": "備考"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "指標を収集する際、常に次の条件が適用されます..."
},
- "onboardingMetametricsDisagree": {
- "message": "結構です"
- },
"onboardingMetametricsInfuraTerms": {
"message": "このデータを他の目的に使用する際は、お知らせします。詳細は当社の$1をご覧ください。設定でいつでもオプトアウトできます。",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json
index ca2d3871d633..a4b9ca10e7b0 100644
--- a/app/_locales/ko/messages.json
+++ b/app/_locales/ko/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "허용"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "자동 감지를 통해 MetaMask가 NFT를 감지하고 표시하도록 허용합니다. 다음과 같은 작업을 할 수 있습니다."
- },
- "allowMetaMaskToDetectTokens": {
- "message": "자동 감지를 통해 MetaMask가 토큰을 감지하고 표시하도록 허용합니다. 다음과 같은 작업을 할 수 있습니다."
- },
"allowMmiToConnectToCustodian": {
"message": "허용할 경우, MMI가 $1에 연결하여 계정을 가져올 수 있습니다."
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "NFT 미디어와 데이터를 표시하면 IP 주소가 OpenSea나 기타 제삼자에게 노출될 수 있습니다. 공격자는 이를 통해 회원님의 IP 주소와 이더리움 주소를 연결할 수 있습니다. NFT 자동 감지는 이 설정을 사용하며, 이 설정이 꺼져 있는 경우 사용할 수 없습니다."
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "NFT 바로 사용"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "토큰 바로 사용"
- },
"doNotShare": {
"message": "누구와도 공유하지 마세요"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "가스비 가속 편집"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "디지털 자산을 손쉽게 탐색"
- },
"enable": {
"message": "활성화"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " 설정에서 이 기능을 활성화합니다."
},
- "enableNftAutoDetection": {
- "message": "NFT 자동 감지 활성화"
- },
"enableSnap": {
"message": "활성화"
},
@@ -1765,12 +1747,6 @@
"message": "$1 활성화",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "토큰 자동 감지 활성화"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "기본 기능을 사용하면 Metamask 확장 v12.3.0에서 이 기능이 자동으로 켜집니다"
- },
"enabled": {
"message": "활성화됨"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "NFT에 즉시 액세스"
- },
- "immediateAccessToYourTokens": {
- "message": "토큰에 즉시 액세스"
- },
"import": {
"message": "가져오기",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "가스 부족"
},
- "notRightNow": {
- "message": "나중에"
- },
"note": {
"message": "메모"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "메트릭을 수집할 때는 항상..."
},
- "onboardingMetametricsDisagree": {
- "message": "괜찮습니다"
- },
"onboardingMetametricsInfuraTerms": {
"message": "이 데이터를 다른 목적으로 사용하기로 결정하면 알려드리겠습니다. 자세한 내용은 $1을(를) 참고하세요. 언제든지 설정으로 이동하여 해제할 수 있습니다.",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json
index d532fe9ff04f..5706a91b473a 100644
--- a/app/_locales/pt/messages.json
+++ b/app/_locales/pt/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "Permitir"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "Permita que a MetaMask detecte e exiba seus NFTs com detecção automática. Você será capaz de:"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "Permita que MetaMask detecte e exiba seus tokens com detecção automática. Você será capaz de:"
- },
"allowMmiToConnectToCustodian": {
"message": "Isso permite que o MMI se conecte ao $1 para importar suas contas."
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "Exibir arquivos de mídia e dados de NFTs expõe seu endereço IP à OpenSea ou outros terceiros. Isso pode possibilitar que invasores associem seu endereço IP ao seu endereço Ethereum. A detecção automática de NFTs depende dessa configuração e ficará indisponível quando ela estiver desativada."
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "Acessar diretamente e começar a usar seus NFTs"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "Vá direto aos seus tokens e comece a usá-los"
- },
"doNotShare": {
"message": "Não compartilhe isso com ninguém"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "Editar taxa de gás para aceleração"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "Navegue sem esforço em seus ativos digitais"
- },
"enable": {
"message": "Ativar"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " Ative nas Configurações."
},
- "enableNftAutoDetection": {
- "message": "Ativar detecção automática de NFTs"
- },
"enableSnap": {
"message": "Ativar"
},
@@ -1765,12 +1747,6 @@
"message": "ativar $1",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "Ativar detecção automática de tokens"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "Essa opção estará automaticamente ativada na extensão da Metamask v12.3.0 para usuários que tenham a funcionalidade básica ativada"
- },
"enabled": {
"message": "Ativado"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "Acessar suas NFTs imediatamente"
- },
- "immediateAccessToYourTokens": {
- "message": "Acesso imediato aos seus tokens"
- },
"import": {
"message": "Importar",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "Não há gás suficiente"
},
- "notRightNow": {
- "message": "Agora não"
- },
"note": {
"message": "Observação"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "Quando coletamos as métricas, elas sempre são..."
},
- "onboardingMetametricsDisagree": {
- "message": "Não, obrigado"
- },
"onboardingMetametricsInfuraTerms": {
"message": "Informaremos a você se decidirmos usar esses dados para outras finalidades. Você pode analisar nossa $1 para obter mais informações. Lembre-se: você pode acessar as configurações e revogar a permissão a qualquer momento.",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json
index 2467ee48a573..d08ae9c67865 100644
--- a/app/_locales/ru/messages.json
+++ b/app/_locales/ru/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "Разрешить"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "Разрешите MetaMask обнаруживать и отображать ваши NFT-токены с помощью автоопределения. Вы сможете:"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "Разрешите MetaMask обнаруживать и отображать ваши токены с помощью автоопределения. Вы сможете:"
- },
"allowMmiToConnectToCustodian": {
"message": "Это позволит MMI подключиться к $1 для импорта ваших счетов."
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "Отображение носителя и данных NFT раскрывает ваш IP-адрес для OpenSea или других третьих сторон. Это может позволить злоумышленникам связать ваш IP-адрес с вашим адресом Ethereum. Автоопределение NFT зависит от этого параметра и будет недоступно, если он отключен."
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "Перейдите прямо к использованию своих NFT-токенов"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "Перейдите прямо к использованию своих токенов"
- },
"doNotShare": {
"message": "Не сообщайте ее никому"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "Изменить плату за газ за ускорение"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "Легко перемещайтесь по своим цифровым активам"
- },
"enable": {
"message": "Включить"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " Включите его в Настройках."
},
- "enableNftAutoDetection": {
- "message": "Включить автоопределение NFT"
- },
"enableSnap": {
"message": "Включить"
},
@@ -1765,12 +1747,6 @@
"message": "активирует для $1",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "Включите автоопределение токена"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "Для пользователей, у которых включен переключатель базового функционала, он будет автоматически включен в расширении Metamask v12.3.0"
- },
"enabled": {
"message": "Включено"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "Немедленный доступ к вашим NFT-токенам"
- },
- "immediateAccessToYourTokens": {
- "message": "Немедленный доступ к вашим токенам"
- },
"import": {
"message": "Импорт",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "Недостаточно газа"
},
- "notRightNow": {
- "message": "Не сейчас"
- },
"note": {
"message": "Примечание"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "Когда мы собираем показатели, они всегда будут..."
},
- "onboardingMetametricsDisagree": {
- "message": "Нет, спасибо"
- },
"onboardingMetametricsInfuraTerms": {
"message": "Мы сообщим вам, если решим использовать эти данные для других целей. Вы можете ознакомиться с нашей $1 для получения дополнительной информации. Помните, что вы можете перейти в настройки и отказаться в любой момент.",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json
index e6e0ef7025b7..65268e6199d6 100644
--- a/app/_locales/tl/messages.json
+++ b/app/_locales/tl/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "Payagan"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "Pahintulutan ang MetaMask na i-detect at ipakita ang iyong mga NFT gamit ang autodetection. Maaari mong:"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "Pahintulutan ang MetaMask na i-detect at ipakita ang iyong mga token gamit ang autodetection. Maaari mong:"
- },
"allowMmiToConnectToCustodian": {
"message": "Papayagan nito ang MMI na kumonekto sa $1 para i-import ang iyong mga account."
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "Ang pagpapakita ng NFT media at data ay naglalantad sa iyong IP address sa OpenSea o sa ibang mga third party. Maaari nitong payagan ang mga umaatake na iugnay ang iyong IP address sa iyong Ethereum address. Umaasa ang awtomatikong pagtuklas ng NFT sa setting na ito, at hindi magagamit kapag naka-off ito."
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "Dumiretso sa paggamit ng iyong mga NFT"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "Dumiretso sa paggamit ng iyong mga token"
- },
"doNotShare": {
"message": "Huwag ibahagi ito sa sinuman"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "I-edit ang pagpapabilis ng bayad sa gas"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "Walang hirap na pamahalaan ang iyong mga digital na asset"
- },
"enable": {
"message": "Payagan"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " Paganahin ito mula sa Mga Setting."
},
- "enableNftAutoDetection": {
- "message": "Paganahin ang autodetection ng NFT"
- },
"enableSnap": {
"message": "Paganahin"
},
@@ -1765,12 +1747,6 @@
"message": "paganahin ang $1",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "Paganahin ang autodetection ng token"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "Ang mga user na naka-toggle on ang Basic Functionality ay awtomatikong naka-on sa Extension ng MetaMask v12.3.0"
- },
"enabled": {
"message": "Pinagana"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "Agad na i-access ang mga NFT mo"
- },
- "immediateAccessToYourTokens": {
- "message": "Agarang access sa iyong mga token"
- },
"import": {
"message": "Mag-import",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "Hindi Sapat ang Gas"
},
- "notRightNow": {
- "message": "Hindi ngayon"
- },
"note": {
"message": "Tala"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "Kapag kami ay nangangalap ng metrics, ito ay palaging..."
},
- "onboardingMetametricsDisagree": {
- "message": "Salamat nalang"
- },
"onboardingMetametricsInfuraTerms": {
"message": "Ipapaalam namin sa iyo kung magdesisyon kaming gamitin ang data na ito para sa ibang layunin. Maaari mong suriin ang aming $1 para sa karagdagang impormasyon. Tandaan, maaari kang magpunta sa mga setting at mag-opt out anumang oras.",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json
index 21af1e89ee17..b58a54040cb1 100644
--- a/app/_locales/tr/messages.json
+++ b/app/_locales/tr/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "İzin Ver"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "MetaMask'in otomatik algılama ile NFT'lerinizi algılamasına ve göstermesine izin verin. Şunları yapabileceksiniz:"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "MetaMask'in otomatik algılama ile token'lerinizi algılamasına ve göstermesine izin verin. Şunları yapabileceksiniz:"
- },
"allowMmiToConnectToCustodian": {
"message": "MMI'nin hesaplarınızı içe aktarmak için $1 ile bağlantı kurmasına izin verir."
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "NFT medyasının ve verilerin gösterilmesi IP adresinizin OpenSea veya diğer üçüncü taraflarla paylaşılmasına neden olur. Bu durum, saldırganların IP adresinizi Ethereum adresinizle ilişkilendirmesini sağlayabilir. NFT otomatik algılama bu ayara dayalıdır ve bu ayar kapatıldığında kullanılamaz olur."
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "Doğrudan NFT'lerinizi kullanmaya başlayın"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "Doğrudan token'lerinizi kullanmaya başlayın"
- },
"doNotShare": {
"message": "Bunu hiç kimseyle paylaşmayın"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "Hızlandırma gaz ücretini düzenle"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "Dijital varlıklarınızda zahmetsizce gezinin"
- },
"enable": {
"message": "Etkinleştir"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " Ayarlardan etkinleştir."
},
- "enableNftAutoDetection": {
- "message": "NFT otomatik algılamayı etkinleştir"
- },
"enableSnap": {
"message": "Etkinleştir"
},
@@ -1765,12 +1747,6 @@
"message": "şunu etkinleştir: $1",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "Otomatik token algılamayı etkinleştir"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "Temel İşlevsellik seçeneği açık olan kullanıcılarda bu seçenek MetaMask Uzantısı 12.3.0 sürümünde otomatik olarak açık olacaktır"
- },
"enabled": {
"message": "Etkinleştirildi"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "NFT'lerinize anında erişin"
- },
- "immediateAccessToYourTokens": {
- "message": "Token'lerinize derhal erişim"
- },
"import": {
"message": "İçe Aktar",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "Yeterli gaz yok"
},
- "notRightNow": {
- "message": "Şimdi değil"
- },
"note": {
"message": "Not"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "Ölçümleri toplarken bu her zaman aşağıdaki gibi olacaktır..."
},
- "onboardingMetametricsDisagree": {
- "message": "Hayır, istemiyorum"
- },
"onboardingMetametricsInfuraTerms": {
"message": "Bu verileri başka amaçlar için kullanmaya karar vermemiz durumunda sizi bilgilendireceğiz. Daha fazla bilgi için $1 bölümümüzü inceleyebilirsiniz. Unutmayın, dilediğiniz zaman ayarlar kısmına giderek vazgeçebilirsiniz.",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json
index 746b7a9178ea..bc956cf2e936 100644
--- a/app/_locales/vi/messages.json
+++ b/app/_locales/vi/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "Cho phép"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "Cho phép MetaMask phát hiện và hiển thị NFT của bạn bằng tính năng tự động phát hiện. Bạn sẽ có thể:"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "Cho phép MetaMask phát hiện và hiển thị token của bạn bằng tính năng tự động phát hiện. Bạn sẽ có thể:"
- },
"allowMmiToConnectToCustodian": {
"message": "Điều này sẽ cho phép MMI kết nối với $1 để nhập tài khoản của bạn."
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "Việc hiển thị dữ liệu và phương tiện NFT sẽ làm lộ địa chỉ IP của bạn với OpenSea hoặc các bên thứ ba khác. Điều này có thể cho phép kẻ tấn công liên kết địa chỉ IP với địa chỉ Ethereum của bạn. Tính năng tự động phát hiện NFT dựa trên chế độ cài đặt này và sẽ không khả dụng khi chế độ cài đặt này bị tắt."
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "Bắt đầu sử dụng NFT của bạn ngay lập tức"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "Bắt đầu sử dụng token của bạn ngay lập tức"
- },
"doNotShare": {
"message": "Không chia sẻ thông tin này với bất kỳ ai"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "Chỉnh sửa phí gas tăng tốc"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "Dễ dàng quản lý tài sản kỹ thuật số của bạn"
- },
"enable": {
"message": "Bật"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " Bật trong Cài Đặt."
},
- "enableNftAutoDetection": {
- "message": "Bật tính năng tự động phát hiện NFT"
- },
"enableSnap": {
"message": "Bật"
},
@@ -1765,12 +1747,6 @@
"message": "bật $1",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "Bật tính năng tự động phát hiện token"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "Người dùng đã bật công tắc Chức năng cơ bản sẽ tự động bật tính năng này trong Tiện ích mở rộng Metamask v12.3.0"
- },
"enabled": {
"message": "Đã bật"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "Truy cập ngay lập tức vào NFT của bạn"
- },
- "immediateAccessToYourTokens": {
- "message": "Truy cập ngay vào các token của bạn"
- },
"import": {
"message": "Nhập",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "Không đủ phí gas"
},
- "notRightNow": {
- "message": "Không phải bây giờ"
- },
"note": {
"message": "Ghi chú"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "Khi thu thập số liệu, chúng tôi sẽ luôn cam kết điều này..."
},
- "onboardingMetametricsDisagree": {
- "message": "Không, cảm ơn"
- },
"onboardingMetametricsInfuraTerms": {
"message": "Chúng tôi sẽ thông báo cho bạn nếu chúng tôi quyết định sử dụng dữ liệu này cho các mục đích khác. Bạn có thể xem lại $1 của chúng tôi để biết thêm thông tin. Lưu ý, bạn có thể truy cập cài đặt và chọn không tham gia bất kỳ lúc nào.",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json
index 853d830ed19f..7265f579a30f 100644
--- a/app/_locales/zh_CN/messages.json
+++ b/app/_locales/zh_CN/messages.json
@@ -513,12 +513,6 @@
"allow": {
"message": "允许"
},
- "allowMetaMaskToDetectNFTs": {
- "message": "允许 MetaMask 使用自动检测功能检测并显示您的 NFT。您将能够:"
- },
- "allowMetaMaskToDetectTokens": {
- "message": "允许 MetaMask 使用自动检测功能检测并显示您的代币。您将能够:"
- },
"allowMmiToConnectToCustodian": {
"message": "这将允许 MMI 连接到 $1,以导入您的账户。"
},
@@ -1606,12 +1600,6 @@
"displayNftMediaDescription": {
"message": "显示 NFT 媒体和数据会将您的 IP 地址暴露给 OpenSea 或其他第三方。这可以让攻击者将您的 IP 地址与您的以太坊地址相关联。NFT 自动检测依赖于此设置,当此设置关闭时将无法使用。"
},
- "diveStraightIntoUsingYourNFTs": {
- "message": "直接开始使用您的 NFT"
- },
- "diveStraightIntoUsingYourTokens": {
- "message": "直接开始使用您的代币"
- },
"doNotShare": {
"message": "请勿与任何人分享此信息"
},
@@ -1743,9 +1731,6 @@
"editSpeedUpEditGasFeeModalTitle": {
"message": "编辑加速燃料费用"
},
- "effortlesslyNavigateYourDigitalAssets": {
- "message": "轻松浏览您的数字资产"
- },
"enable": {
"message": "启用"
},
@@ -1755,9 +1740,6 @@
"enableFromSettings": {
"message": " 从设置中启用它。"
},
- "enableNftAutoDetection": {
- "message": "启用 NFT 自动检测"
- },
"enableSnap": {
"message": "启用"
},
@@ -1765,12 +1747,6 @@
"message": "启用 $1",
"description": "$1 is a token symbol, e.g. ETH"
},
- "enableTokenAutoDetection": {
- "message": "启用代币自动检测"
- },
- "enable_auto_detection_toggle_automatically": {
- "message": "启用基本功能的用户将在 MetaMask Extension v12.3.0 中自动启用此功能"
- },
"enabled": {
"message": "已启用"
},
@@ -2283,12 +2259,6 @@
"imToken": {
"message": "imToken"
},
- "immediateAccessToYourNFTs": {
- "message": "立即访问您的 NFT"
- },
- "immediateAccessToYourTokens": {
- "message": "即时访问您的代币"
- },
"import": {
"message": "导入",
"description": "Button to import an account from a selected file"
@@ -3253,9 +3223,6 @@
"notEnoughGas": {
"message": "燃料不足"
},
- "notRightNow": {
- "message": "暂时不"
- },
"note": {
"message": "单据"
},
@@ -3526,9 +3493,6 @@
"onboardingMetametricsDescription2": {
"message": "当我们收集指标时,总是..."
},
- "onboardingMetametricsDisagree": {
- "message": "不,谢谢"
- },
"onboardingMetametricsInfuraTerms": {
"message": "如果我们决定将这些数据用于其他目的,我们会通知您。您可以查看我们的 $1 以了解更多信息。请记住,您可以随时转到设置并选择退出。",
"description": "$1 represents `onboardingMetametricsInfuraTermsPolicy`"
From 8c1d8443a20e7fb1b8e584727231db2ab7a81e89 Mon Sep 17 00:00:00 2001
From: MetaMask Bot
Date: Mon, 9 Sep 2024 15:51:09 +0000
Subject: [PATCH 05/43] Update LavaMoat policies
---
lavamoat/browserify/beta/policy.json | 242 ++++++++++++++++----------
lavamoat/browserify/flask/policy.json | 242 ++++++++++++++++----------
lavamoat/browserify/main/policy.json | 242 ++++++++++++++++----------
lavamoat/browserify/mmi/policy.json | 242 ++++++++++++++++----------
4 files changed, 588 insertions(+), 380 deletions(-)
diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json
index eee2bda9aeb1..eb3caba43c21 100644
--- a/lavamoat/browserify/beta/policy.json
+++ b/lavamoat/browserify/beta/policy.json
@@ -788,8 +788,23 @@
},
"@metamask/abi-utils": {
"packages": {
- "@metamask/utils": true,
- "superstruct": true
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/utils": true
+ }
+ },
+ "@metamask/abi-utils>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
+ "packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
"@metamask/accounts-controller": {
@@ -797,10 +812,10 @@
"@ethereumjs/tx>@ethereumjs/util": true,
"@ethereumjs/tx>ethereum-cryptography": true,
"@metamask/accounts-controller>@metamask/base-controller": true,
+ "@metamask/accounts-controller>@metamask/utils": true,
"@metamask/eth-snap-keyring": true,
"@metamask/keyring-api": true,
"@metamask/keyring-controller": true,
- "@metamask/utils": true,
"uuid": true
}
},
@@ -812,6 +827,21 @@
"immer": true
}
},
+ "@metamask/accounts-controller>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
+ "packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
+ }
+ },
"@metamask/address-book-controller": {
"packages": {
"@metamask/address-book-controller>@metamask/controller-utils": true,
@@ -952,7 +982,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1095,7 +1125,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1144,33 +1174,27 @@
"setTimeout": true
},
"packages": {
- "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": true,
+ "@metamask/eth-json-rpc-middleware>@metamask/utils": true,
"@metamask/eth-json-rpc-middleware>klona": true,
"@metamask/eth-json-rpc-middleware>safe-stable-stringify": true,
"@metamask/eth-sig-util": true,
"@metamask/rpc-errors": true,
- "@metamask/utils": true,
- "pify": true
- }
- },
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": {
- "packages": {
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": true,
- "@metamask/safe-event-emitter": true
- }
- },
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": {
- "packages": {
- "@metamask/rpc-errors": true,
- "@metamask/safe-event-emitter": true,
- "@metamask/utils": true
+ "@metamask/snaps-controllers>@metamask/json-rpc-engine": true
}
},
- "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": {
+ "@metamask/eth-json-rpc-middleware>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
"packages": {
- "@metamask/rpc-errors": true,
- "@metamask/safe-event-emitter": true,
- "@metamask/utils": true
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
"@metamask/eth-ledger-bridge-keyring": {
@@ -1203,26 +1227,32 @@
"@ethereumjs/tx>@ethereumjs/util": true,
"@ethereumjs/tx>ethereum-cryptography": true,
"@metamask/abi-utils": true,
+ "@metamask/eth-sig-util>@metamask/utils": true,
"@metamask/eth-sig-util>tweetnacl": true,
- "@metamask/eth-sig-util>tweetnacl-util": true,
- "@metamask/utils": true,
+ "@metamask/utils>@scure/base": true,
"browserify>buffer": true
}
},
- "@metamask/eth-sig-util>tweetnacl": {
+ "@metamask/eth-sig-util>@metamask/utils": {
"globals": {
- "crypto": true,
- "msCrypto": true,
- "nacl": "write"
+ "TextDecoder": true,
+ "TextEncoder": true
},
"packages": {
- "browserify>browser-resolve": true
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
- "@metamask/eth-sig-util>tweetnacl-util": {
+ "@metamask/eth-sig-util>tweetnacl": {
"globals": {
- "atob": true,
- "btoa": true
+ "crypto": true,
+ "msCrypto": true,
+ "nacl": "write"
},
"packages": {
"browserify>browser-resolve": true
@@ -1372,8 +1402,8 @@
"@ethereumjs/tx": true,
"@ethereumjs/tx>@ethereumjs/util": true,
"@metamask/eth-trezor-keyring>@trezor/connect-plugin-ethereum": true,
- "@metamask/eth-trezor-keyring>@trezor/connect-web": true,
"@metamask/eth-trezor-keyring>hdkey": true,
+ "@trezor/connect-web": true,
"browserify>buffer": true,
"webpack>events": true
}
@@ -1384,37 +1414,6 @@
"@swc/helpers>tslib": true
}
},
- "@metamask/eth-trezor-keyring>@trezor/connect-web": {
- "globals": {
- "URLSearchParams": true,
- "__TREZOR_CONNECT_SRC": true,
- "addEventListener": true,
- "btoa": true,
- "chrome": true,
- "clearInterval": true,
- "clearTimeout": true,
- "console.warn": true,
- "document.body": true,
- "document.createElement": true,
- "document.createTextNode": true,
- "document.getElementById": true,
- "document.querySelectorAll": true,
- "location": true,
- "navigator": true,
- "open": true,
- "origin": true,
- "removeEventListener": true,
- "setInterval": true,
- "setTimeout": true
- },
- "packages": {
- "@swc/helpers>tslib": true,
- "@trezor/connect-web>@trezor/connect": true,
- "@trezor/connect-web>@trezor/connect-common": true,
- "@trezor/connect-web>@trezor/utils": true,
- "webpack>events": true
- }
- },
"@metamask/eth-trezor-keyring>hdkey": {
"packages": {
"browserify>assert": true,
@@ -1582,7 +1581,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1648,10 +1647,25 @@
"URL": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/keyring-api>@metamask/utils": true,
"@metamask/keyring-api>bech32": true,
- "@metamask/keyring-api>uuid": true,
- "@metamask/utils": true,
- "superstruct": true
+ "@metamask/keyring-api>uuid": true
+ }
+ },
+ "@metamask/keyring-api>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
+ "packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
"@metamask/keyring-api>uuid": {
@@ -1709,7 +1723,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1885,7 +1899,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1911,12 +1925,12 @@
"setTimeout": true
},
"packages": {
- "@metamask/eth-json-rpc-middleware": true,
"@metamask/eth-query": true,
"@metamask/eth-token-tracker>@metamask/eth-block-tracker": true,
"@metamask/network-controller>@metamask/base-controller": true,
"@metamask/network-controller>@metamask/controller-utils": true,
"@metamask/network-controller>@metamask/eth-json-rpc-infura": true,
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware": true,
"@metamask/network-controller>@metamask/eth-json-rpc-provider": true,
"@metamask/network-controller>@metamask/swappable-obj-proxy": true,
"@metamask/rpc-errors": true,
@@ -1958,7 +1972,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1972,13 +1986,19 @@
"setTimeout": true
},
"packages": {
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": true,
+ "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": true,
"@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true,
"@metamask/rpc-errors": true,
"@metamask/utils": true,
"node-fetch": true
}
},
+ "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": {
+ "packages": {
+ "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true,
+ "@metamask/safe-event-emitter": true
+ }
+ },
"@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": {
"packages": {
"@metamask/rpc-errors": true,
@@ -1986,6 +2006,29 @@
"@metamask/utils": true
}
},
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware": {
+ "globals": {
+ "URL": true,
+ "console.error": true,
+ "setTimeout": true
+ },
+ "packages": {
+ "@metamask/eth-json-rpc-middleware>klona": true,
+ "@metamask/eth-json-rpc-middleware>safe-stable-stringify": true,
+ "@metamask/eth-sig-util": true,
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": true,
+ "@metamask/rpc-errors": true,
+ "@metamask/utils": true,
+ "pify": true
+ }
+ },
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": {
+ "packages": {
+ "@metamask/rpc-errors": true,
+ "@metamask/safe-event-emitter": true,
+ "@metamask/utils": true
+ }
+ },
"@metamask/network-controller>@metamask/eth-json-rpc-provider": {
"packages": {
"@metamask/rpc-errors": true,
@@ -2073,7 +2116,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2312,7 +2355,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2503,7 +2546,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2690,7 +2733,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2716,7 +2759,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2764,7 +2807,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2846,13 +2889,13 @@
"fetch": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/eth-snap-keyring>@metamask/snaps-utils>@metamask/slip44": true,
"@metamask/rpc-errors": true,
"@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/permission-controller": true,
"@metamask/snaps-execution-environments>@metamask/utils": true,
"@metamask/snaps-sdk": true,
"@metamask/snaps-sdk>@metamask/key-tree": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils>cron-parser": true,
"@metamask/snaps-utils>fast-json-stable-stringify": true,
"@metamask/snaps-utils>fast-xml-parser": true,
@@ -2912,7 +2955,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2928,12 +2971,12 @@
},
"@metamask/snaps-rpc-methods": {
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/rpc-errors": true,
"@metamask/snaps-rpc-methods>@metamask/permission-controller": true,
"@metamask/snaps-rpc-methods>@metamask/utils": true,
"@metamask/snaps-sdk": true,
"@metamask/snaps-sdk>@metamask/key-tree": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils": true,
"@noble/hashes": true
}
@@ -2990,7 +3033,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3004,8 +3047,8 @@
"fetch": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/rpc-errors": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-sdk>@metamask/utils": true
}
},
@@ -3024,7 +3067,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3039,7 +3082,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3064,10 +3107,10 @@
"fetch": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/rpc-errors": true,
"@metamask/snaps-sdk": true,
"@metamask/snaps-sdk>@metamask/key-tree": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils>@metamask/permission-controller": true,
"@metamask/snaps-utils>@metamask/slip44": true,
"@metamask/snaps-utils>@metamask/utils": true,
@@ -3131,8 +3174,8 @@
},
"@metamask/snaps-utils>@metamask/snaps-registry": {
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/message-signing-snap>@noble/curves": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils>@metamask/snaps-registry>@metamask/utils": true,
"@noble/hashes": true
}
@@ -3143,7 +3186,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3158,7 +3201,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3322,7 +3365,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3399,7 +3442,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3802,19 +3845,28 @@
"globals": {
"AbortController": true,
"Intl.NumberFormat": true,
+ "clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.info": true,
"console.log": true,
"console.warn": true,
+ "setInterval": true,
"setTimeout": true
},
"packages": {
"@swc/helpers>tslib": true,
+ "@trezor/connect-web>@trezor/utils>bignumber.js": true,
"browserify>buffer": true,
"webpack>events": true
}
},
+ "@trezor/connect-web>@trezor/utils>bignumber.js": {
+ "globals": {
+ "crypto": true,
+ "define": true
+ }
+ },
"@welldone-software/why-did-you-render": {
"globals": {
"Element": true,
diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json
index eee2bda9aeb1..eb3caba43c21 100644
--- a/lavamoat/browserify/flask/policy.json
+++ b/lavamoat/browserify/flask/policy.json
@@ -788,8 +788,23 @@
},
"@metamask/abi-utils": {
"packages": {
- "@metamask/utils": true,
- "superstruct": true
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/utils": true
+ }
+ },
+ "@metamask/abi-utils>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
+ "packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
"@metamask/accounts-controller": {
@@ -797,10 +812,10 @@
"@ethereumjs/tx>@ethereumjs/util": true,
"@ethereumjs/tx>ethereum-cryptography": true,
"@metamask/accounts-controller>@metamask/base-controller": true,
+ "@metamask/accounts-controller>@metamask/utils": true,
"@metamask/eth-snap-keyring": true,
"@metamask/keyring-api": true,
"@metamask/keyring-controller": true,
- "@metamask/utils": true,
"uuid": true
}
},
@@ -812,6 +827,21 @@
"immer": true
}
},
+ "@metamask/accounts-controller>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
+ "packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
+ }
+ },
"@metamask/address-book-controller": {
"packages": {
"@metamask/address-book-controller>@metamask/controller-utils": true,
@@ -952,7 +982,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1095,7 +1125,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1144,33 +1174,27 @@
"setTimeout": true
},
"packages": {
- "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": true,
+ "@metamask/eth-json-rpc-middleware>@metamask/utils": true,
"@metamask/eth-json-rpc-middleware>klona": true,
"@metamask/eth-json-rpc-middleware>safe-stable-stringify": true,
"@metamask/eth-sig-util": true,
"@metamask/rpc-errors": true,
- "@metamask/utils": true,
- "pify": true
- }
- },
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": {
- "packages": {
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": true,
- "@metamask/safe-event-emitter": true
- }
- },
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": {
- "packages": {
- "@metamask/rpc-errors": true,
- "@metamask/safe-event-emitter": true,
- "@metamask/utils": true
+ "@metamask/snaps-controllers>@metamask/json-rpc-engine": true
}
},
- "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": {
+ "@metamask/eth-json-rpc-middleware>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
"packages": {
- "@metamask/rpc-errors": true,
- "@metamask/safe-event-emitter": true,
- "@metamask/utils": true
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
"@metamask/eth-ledger-bridge-keyring": {
@@ -1203,26 +1227,32 @@
"@ethereumjs/tx>@ethereumjs/util": true,
"@ethereumjs/tx>ethereum-cryptography": true,
"@metamask/abi-utils": true,
+ "@metamask/eth-sig-util>@metamask/utils": true,
"@metamask/eth-sig-util>tweetnacl": true,
- "@metamask/eth-sig-util>tweetnacl-util": true,
- "@metamask/utils": true,
+ "@metamask/utils>@scure/base": true,
"browserify>buffer": true
}
},
- "@metamask/eth-sig-util>tweetnacl": {
+ "@metamask/eth-sig-util>@metamask/utils": {
"globals": {
- "crypto": true,
- "msCrypto": true,
- "nacl": "write"
+ "TextDecoder": true,
+ "TextEncoder": true
},
"packages": {
- "browserify>browser-resolve": true
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
- "@metamask/eth-sig-util>tweetnacl-util": {
+ "@metamask/eth-sig-util>tweetnacl": {
"globals": {
- "atob": true,
- "btoa": true
+ "crypto": true,
+ "msCrypto": true,
+ "nacl": "write"
},
"packages": {
"browserify>browser-resolve": true
@@ -1372,8 +1402,8 @@
"@ethereumjs/tx": true,
"@ethereumjs/tx>@ethereumjs/util": true,
"@metamask/eth-trezor-keyring>@trezor/connect-plugin-ethereum": true,
- "@metamask/eth-trezor-keyring>@trezor/connect-web": true,
"@metamask/eth-trezor-keyring>hdkey": true,
+ "@trezor/connect-web": true,
"browserify>buffer": true,
"webpack>events": true
}
@@ -1384,37 +1414,6 @@
"@swc/helpers>tslib": true
}
},
- "@metamask/eth-trezor-keyring>@trezor/connect-web": {
- "globals": {
- "URLSearchParams": true,
- "__TREZOR_CONNECT_SRC": true,
- "addEventListener": true,
- "btoa": true,
- "chrome": true,
- "clearInterval": true,
- "clearTimeout": true,
- "console.warn": true,
- "document.body": true,
- "document.createElement": true,
- "document.createTextNode": true,
- "document.getElementById": true,
- "document.querySelectorAll": true,
- "location": true,
- "navigator": true,
- "open": true,
- "origin": true,
- "removeEventListener": true,
- "setInterval": true,
- "setTimeout": true
- },
- "packages": {
- "@swc/helpers>tslib": true,
- "@trezor/connect-web>@trezor/connect": true,
- "@trezor/connect-web>@trezor/connect-common": true,
- "@trezor/connect-web>@trezor/utils": true,
- "webpack>events": true
- }
- },
"@metamask/eth-trezor-keyring>hdkey": {
"packages": {
"browserify>assert": true,
@@ -1582,7 +1581,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1648,10 +1647,25 @@
"URL": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/keyring-api>@metamask/utils": true,
"@metamask/keyring-api>bech32": true,
- "@metamask/keyring-api>uuid": true,
- "@metamask/utils": true,
- "superstruct": true
+ "@metamask/keyring-api>uuid": true
+ }
+ },
+ "@metamask/keyring-api>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
+ "packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
"@metamask/keyring-api>uuid": {
@@ -1709,7 +1723,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1885,7 +1899,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1911,12 +1925,12 @@
"setTimeout": true
},
"packages": {
- "@metamask/eth-json-rpc-middleware": true,
"@metamask/eth-query": true,
"@metamask/eth-token-tracker>@metamask/eth-block-tracker": true,
"@metamask/network-controller>@metamask/base-controller": true,
"@metamask/network-controller>@metamask/controller-utils": true,
"@metamask/network-controller>@metamask/eth-json-rpc-infura": true,
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware": true,
"@metamask/network-controller>@metamask/eth-json-rpc-provider": true,
"@metamask/network-controller>@metamask/swappable-obj-proxy": true,
"@metamask/rpc-errors": true,
@@ -1958,7 +1972,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1972,13 +1986,19 @@
"setTimeout": true
},
"packages": {
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": true,
+ "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": true,
"@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true,
"@metamask/rpc-errors": true,
"@metamask/utils": true,
"node-fetch": true
}
},
+ "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": {
+ "packages": {
+ "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true,
+ "@metamask/safe-event-emitter": true
+ }
+ },
"@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": {
"packages": {
"@metamask/rpc-errors": true,
@@ -1986,6 +2006,29 @@
"@metamask/utils": true
}
},
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware": {
+ "globals": {
+ "URL": true,
+ "console.error": true,
+ "setTimeout": true
+ },
+ "packages": {
+ "@metamask/eth-json-rpc-middleware>klona": true,
+ "@metamask/eth-json-rpc-middleware>safe-stable-stringify": true,
+ "@metamask/eth-sig-util": true,
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": true,
+ "@metamask/rpc-errors": true,
+ "@metamask/utils": true,
+ "pify": true
+ }
+ },
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": {
+ "packages": {
+ "@metamask/rpc-errors": true,
+ "@metamask/safe-event-emitter": true,
+ "@metamask/utils": true
+ }
+ },
"@metamask/network-controller>@metamask/eth-json-rpc-provider": {
"packages": {
"@metamask/rpc-errors": true,
@@ -2073,7 +2116,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2312,7 +2355,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2503,7 +2546,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2690,7 +2733,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2716,7 +2759,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2764,7 +2807,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2846,13 +2889,13 @@
"fetch": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/eth-snap-keyring>@metamask/snaps-utils>@metamask/slip44": true,
"@metamask/rpc-errors": true,
"@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/permission-controller": true,
"@metamask/snaps-execution-environments>@metamask/utils": true,
"@metamask/snaps-sdk": true,
"@metamask/snaps-sdk>@metamask/key-tree": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils>cron-parser": true,
"@metamask/snaps-utils>fast-json-stable-stringify": true,
"@metamask/snaps-utils>fast-xml-parser": true,
@@ -2912,7 +2955,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2928,12 +2971,12 @@
},
"@metamask/snaps-rpc-methods": {
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/rpc-errors": true,
"@metamask/snaps-rpc-methods>@metamask/permission-controller": true,
"@metamask/snaps-rpc-methods>@metamask/utils": true,
"@metamask/snaps-sdk": true,
"@metamask/snaps-sdk>@metamask/key-tree": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils": true,
"@noble/hashes": true
}
@@ -2990,7 +3033,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3004,8 +3047,8 @@
"fetch": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/rpc-errors": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-sdk>@metamask/utils": true
}
},
@@ -3024,7 +3067,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3039,7 +3082,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3064,10 +3107,10 @@
"fetch": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/rpc-errors": true,
"@metamask/snaps-sdk": true,
"@metamask/snaps-sdk>@metamask/key-tree": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils>@metamask/permission-controller": true,
"@metamask/snaps-utils>@metamask/slip44": true,
"@metamask/snaps-utils>@metamask/utils": true,
@@ -3131,8 +3174,8 @@
},
"@metamask/snaps-utils>@metamask/snaps-registry": {
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/message-signing-snap>@noble/curves": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils>@metamask/snaps-registry>@metamask/utils": true,
"@noble/hashes": true
}
@@ -3143,7 +3186,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3158,7 +3201,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3322,7 +3365,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3399,7 +3442,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3802,19 +3845,28 @@
"globals": {
"AbortController": true,
"Intl.NumberFormat": true,
+ "clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.info": true,
"console.log": true,
"console.warn": true,
+ "setInterval": true,
"setTimeout": true
},
"packages": {
"@swc/helpers>tslib": true,
+ "@trezor/connect-web>@trezor/utils>bignumber.js": true,
"browserify>buffer": true,
"webpack>events": true
}
},
+ "@trezor/connect-web>@trezor/utils>bignumber.js": {
+ "globals": {
+ "crypto": true,
+ "define": true
+ }
+ },
"@welldone-software/why-did-you-render": {
"globals": {
"Element": true,
diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json
index eee2bda9aeb1..eb3caba43c21 100644
--- a/lavamoat/browserify/main/policy.json
+++ b/lavamoat/browserify/main/policy.json
@@ -788,8 +788,23 @@
},
"@metamask/abi-utils": {
"packages": {
- "@metamask/utils": true,
- "superstruct": true
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/utils": true
+ }
+ },
+ "@metamask/abi-utils>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
+ "packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
"@metamask/accounts-controller": {
@@ -797,10 +812,10 @@
"@ethereumjs/tx>@ethereumjs/util": true,
"@ethereumjs/tx>ethereum-cryptography": true,
"@metamask/accounts-controller>@metamask/base-controller": true,
+ "@metamask/accounts-controller>@metamask/utils": true,
"@metamask/eth-snap-keyring": true,
"@metamask/keyring-api": true,
"@metamask/keyring-controller": true,
- "@metamask/utils": true,
"uuid": true
}
},
@@ -812,6 +827,21 @@
"immer": true
}
},
+ "@metamask/accounts-controller>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
+ "packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
+ }
+ },
"@metamask/address-book-controller": {
"packages": {
"@metamask/address-book-controller>@metamask/controller-utils": true,
@@ -952,7 +982,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1095,7 +1125,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1144,33 +1174,27 @@
"setTimeout": true
},
"packages": {
- "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": true,
+ "@metamask/eth-json-rpc-middleware>@metamask/utils": true,
"@metamask/eth-json-rpc-middleware>klona": true,
"@metamask/eth-json-rpc-middleware>safe-stable-stringify": true,
"@metamask/eth-sig-util": true,
"@metamask/rpc-errors": true,
- "@metamask/utils": true,
- "pify": true
- }
- },
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": {
- "packages": {
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": true,
- "@metamask/safe-event-emitter": true
- }
- },
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": {
- "packages": {
- "@metamask/rpc-errors": true,
- "@metamask/safe-event-emitter": true,
- "@metamask/utils": true
+ "@metamask/snaps-controllers>@metamask/json-rpc-engine": true
}
},
- "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": {
+ "@metamask/eth-json-rpc-middleware>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
"packages": {
- "@metamask/rpc-errors": true,
- "@metamask/safe-event-emitter": true,
- "@metamask/utils": true
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
"@metamask/eth-ledger-bridge-keyring": {
@@ -1203,26 +1227,32 @@
"@ethereumjs/tx>@ethereumjs/util": true,
"@ethereumjs/tx>ethereum-cryptography": true,
"@metamask/abi-utils": true,
+ "@metamask/eth-sig-util>@metamask/utils": true,
"@metamask/eth-sig-util>tweetnacl": true,
- "@metamask/eth-sig-util>tweetnacl-util": true,
- "@metamask/utils": true,
+ "@metamask/utils>@scure/base": true,
"browserify>buffer": true
}
},
- "@metamask/eth-sig-util>tweetnacl": {
+ "@metamask/eth-sig-util>@metamask/utils": {
"globals": {
- "crypto": true,
- "msCrypto": true,
- "nacl": "write"
+ "TextDecoder": true,
+ "TextEncoder": true
},
"packages": {
- "browserify>browser-resolve": true
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
- "@metamask/eth-sig-util>tweetnacl-util": {
+ "@metamask/eth-sig-util>tweetnacl": {
"globals": {
- "atob": true,
- "btoa": true
+ "crypto": true,
+ "msCrypto": true,
+ "nacl": "write"
},
"packages": {
"browserify>browser-resolve": true
@@ -1372,8 +1402,8 @@
"@ethereumjs/tx": true,
"@ethereumjs/tx>@ethereumjs/util": true,
"@metamask/eth-trezor-keyring>@trezor/connect-plugin-ethereum": true,
- "@metamask/eth-trezor-keyring>@trezor/connect-web": true,
"@metamask/eth-trezor-keyring>hdkey": true,
+ "@trezor/connect-web": true,
"browserify>buffer": true,
"webpack>events": true
}
@@ -1384,37 +1414,6 @@
"@swc/helpers>tslib": true
}
},
- "@metamask/eth-trezor-keyring>@trezor/connect-web": {
- "globals": {
- "URLSearchParams": true,
- "__TREZOR_CONNECT_SRC": true,
- "addEventListener": true,
- "btoa": true,
- "chrome": true,
- "clearInterval": true,
- "clearTimeout": true,
- "console.warn": true,
- "document.body": true,
- "document.createElement": true,
- "document.createTextNode": true,
- "document.getElementById": true,
- "document.querySelectorAll": true,
- "location": true,
- "navigator": true,
- "open": true,
- "origin": true,
- "removeEventListener": true,
- "setInterval": true,
- "setTimeout": true
- },
- "packages": {
- "@swc/helpers>tslib": true,
- "@trezor/connect-web>@trezor/connect": true,
- "@trezor/connect-web>@trezor/connect-common": true,
- "@trezor/connect-web>@trezor/utils": true,
- "webpack>events": true
- }
- },
"@metamask/eth-trezor-keyring>hdkey": {
"packages": {
"browserify>assert": true,
@@ -1582,7 +1581,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1648,10 +1647,25 @@
"URL": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/keyring-api>@metamask/utils": true,
"@metamask/keyring-api>bech32": true,
- "@metamask/keyring-api>uuid": true,
- "@metamask/utils": true,
- "superstruct": true
+ "@metamask/keyring-api>uuid": true
+ }
+ },
+ "@metamask/keyring-api>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
+ "packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
"@metamask/keyring-api>uuid": {
@@ -1709,7 +1723,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1885,7 +1899,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1911,12 +1925,12 @@
"setTimeout": true
},
"packages": {
- "@metamask/eth-json-rpc-middleware": true,
"@metamask/eth-query": true,
"@metamask/eth-token-tracker>@metamask/eth-block-tracker": true,
"@metamask/network-controller>@metamask/base-controller": true,
"@metamask/network-controller>@metamask/controller-utils": true,
"@metamask/network-controller>@metamask/eth-json-rpc-infura": true,
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware": true,
"@metamask/network-controller>@metamask/eth-json-rpc-provider": true,
"@metamask/network-controller>@metamask/swappable-obj-proxy": true,
"@metamask/rpc-errors": true,
@@ -1958,7 +1972,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1972,13 +1986,19 @@
"setTimeout": true
},
"packages": {
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": true,
+ "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": true,
"@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true,
"@metamask/rpc-errors": true,
"@metamask/utils": true,
"node-fetch": true
}
},
+ "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": {
+ "packages": {
+ "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true,
+ "@metamask/safe-event-emitter": true
+ }
+ },
"@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": {
"packages": {
"@metamask/rpc-errors": true,
@@ -1986,6 +2006,29 @@
"@metamask/utils": true
}
},
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware": {
+ "globals": {
+ "URL": true,
+ "console.error": true,
+ "setTimeout": true
+ },
+ "packages": {
+ "@metamask/eth-json-rpc-middleware>klona": true,
+ "@metamask/eth-json-rpc-middleware>safe-stable-stringify": true,
+ "@metamask/eth-sig-util": true,
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": true,
+ "@metamask/rpc-errors": true,
+ "@metamask/utils": true,
+ "pify": true
+ }
+ },
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": {
+ "packages": {
+ "@metamask/rpc-errors": true,
+ "@metamask/safe-event-emitter": true,
+ "@metamask/utils": true
+ }
+ },
"@metamask/network-controller>@metamask/eth-json-rpc-provider": {
"packages": {
"@metamask/rpc-errors": true,
@@ -2073,7 +2116,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2312,7 +2355,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2503,7 +2546,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2690,7 +2733,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2716,7 +2759,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2764,7 +2807,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2846,13 +2889,13 @@
"fetch": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/eth-snap-keyring>@metamask/snaps-utils>@metamask/slip44": true,
"@metamask/rpc-errors": true,
"@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/permission-controller": true,
"@metamask/snaps-execution-environments>@metamask/utils": true,
"@metamask/snaps-sdk": true,
"@metamask/snaps-sdk>@metamask/key-tree": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils>cron-parser": true,
"@metamask/snaps-utils>fast-json-stable-stringify": true,
"@metamask/snaps-utils>fast-xml-parser": true,
@@ -2912,7 +2955,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2928,12 +2971,12 @@
},
"@metamask/snaps-rpc-methods": {
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/rpc-errors": true,
"@metamask/snaps-rpc-methods>@metamask/permission-controller": true,
"@metamask/snaps-rpc-methods>@metamask/utils": true,
"@metamask/snaps-sdk": true,
"@metamask/snaps-sdk>@metamask/key-tree": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils": true,
"@noble/hashes": true
}
@@ -2990,7 +3033,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3004,8 +3047,8 @@
"fetch": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/rpc-errors": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-sdk>@metamask/utils": true
}
},
@@ -3024,7 +3067,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3039,7 +3082,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3064,10 +3107,10 @@
"fetch": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/rpc-errors": true,
"@metamask/snaps-sdk": true,
"@metamask/snaps-sdk>@metamask/key-tree": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils>@metamask/permission-controller": true,
"@metamask/snaps-utils>@metamask/slip44": true,
"@metamask/snaps-utils>@metamask/utils": true,
@@ -3131,8 +3174,8 @@
},
"@metamask/snaps-utils>@metamask/snaps-registry": {
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/message-signing-snap>@noble/curves": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils>@metamask/snaps-registry>@metamask/utils": true,
"@noble/hashes": true
}
@@ -3143,7 +3186,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3158,7 +3201,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3322,7 +3365,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3399,7 +3442,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3802,19 +3845,28 @@
"globals": {
"AbortController": true,
"Intl.NumberFormat": true,
+ "clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.info": true,
"console.log": true,
"console.warn": true,
+ "setInterval": true,
"setTimeout": true
},
"packages": {
"@swc/helpers>tslib": true,
+ "@trezor/connect-web>@trezor/utils>bignumber.js": true,
"browserify>buffer": true,
"webpack>events": true
}
},
+ "@trezor/connect-web>@trezor/utils>bignumber.js": {
+ "globals": {
+ "crypto": true,
+ "define": true
+ }
+ },
"@welldone-software/why-did-you-render": {
"globals": {
"Element": true,
diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json
index 02d132bfc7cd..465b5dcf621b 100644
--- a/lavamoat/browserify/mmi/policy.json
+++ b/lavamoat/browserify/mmi/policy.json
@@ -880,8 +880,23 @@
},
"@metamask/abi-utils": {
"packages": {
- "@metamask/utils": true,
- "superstruct": true
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/utils": true
+ }
+ },
+ "@metamask/abi-utils>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
+ "packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
"@metamask/accounts-controller": {
@@ -889,10 +904,10 @@
"@ethereumjs/tx>@ethereumjs/util": true,
"@ethereumjs/tx>ethereum-cryptography": true,
"@metamask/accounts-controller>@metamask/base-controller": true,
+ "@metamask/accounts-controller>@metamask/utils": true,
"@metamask/eth-snap-keyring": true,
"@metamask/keyring-api": true,
"@metamask/keyring-controller": true,
- "@metamask/utils": true,
"uuid": true
}
},
@@ -904,6 +919,21 @@
"immer": true
}
},
+ "@metamask/accounts-controller>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
+ "packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
+ }
+ },
"@metamask/address-book-controller": {
"packages": {
"@metamask/address-book-controller>@metamask/controller-utils": true,
@@ -1044,7 +1074,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1187,7 +1217,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1236,33 +1266,27 @@
"setTimeout": true
},
"packages": {
- "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": true,
+ "@metamask/eth-json-rpc-middleware>@metamask/utils": true,
"@metamask/eth-json-rpc-middleware>klona": true,
"@metamask/eth-json-rpc-middleware>safe-stable-stringify": true,
"@metamask/eth-sig-util": true,
"@metamask/rpc-errors": true,
- "@metamask/utils": true,
- "pify": true
- }
- },
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": {
- "packages": {
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": true,
- "@metamask/safe-event-emitter": true
- }
- },
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider>@metamask/json-rpc-engine": {
- "packages": {
- "@metamask/rpc-errors": true,
- "@metamask/safe-event-emitter": true,
- "@metamask/utils": true
+ "@metamask/snaps-controllers>@metamask/json-rpc-engine": true
}
},
- "@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": {
+ "@metamask/eth-json-rpc-middleware>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
"packages": {
- "@metamask/rpc-errors": true,
- "@metamask/safe-event-emitter": true,
- "@metamask/utils": true
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
"@metamask/eth-ledger-bridge-keyring": {
@@ -1295,26 +1319,32 @@
"@ethereumjs/tx>@ethereumjs/util": true,
"@ethereumjs/tx>ethereum-cryptography": true,
"@metamask/abi-utils": true,
+ "@metamask/eth-sig-util>@metamask/utils": true,
"@metamask/eth-sig-util>tweetnacl": true,
- "@metamask/eth-sig-util>tweetnacl-util": true,
- "@metamask/utils": true,
+ "@metamask/utils>@scure/base": true,
"browserify>buffer": true
}
},
- "@metamask/eth-sig-util>tweetnacl": {
+ "@metamask/eth-sig-util>@metamask/utils": {
"globals": {
- "crypto": true,
- "msCrypto": true,
- "nacl": "write"
+ "TextDecoder": true,
+ "TextEncoder": true
},
"packages": {
- "browserify>browser-resolve": true
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
- "@metamask/eth-sig-util>tweetnacl-util": {
+ "@metamask/eth-sig-util>tweetnacl": {
"globals": {
- "atob": true,
- "btoa": true
+ "crypto": true,
+ "msCrypto": true,
+ "nacl": "write"
},
"packages": {
"browserify>browser-resolve": true
@@ -1464,8 +1494,8 @@
"@ethereumjs/tx": true,
"@ethereumjs/tx>@ethereumjs/util": true,
"@metamask/eth-trezor-keyring>@trezor/connect-plugin-ethereum": true,
- "@metamask/eth-trezor-keyring>@trezor/connect-web": true,
"@metamask/eth-trezor-keyring>hdkey": true,
+ "@trezor/connect-web": true,
"browserify>buffer": true,
"webpack>events": true
}
@@ -1476,37 +1506,6 @@
"@swc/helpers>tslib": true
}
},
- "@metamask/eth-trezor-keyring>@trezor/connect-web": {
- "globals": {
- "URLSearchParams": true,
- "__TREZOR_CONNECT_SRC": true,
- "addEventListener": true,
- "btoa": true,
- "chrome": true,
- "clearInterval": true,
- "clearTimeout": true,
- "console.warn": true,
- "document.body": true,
- "document.createElement": true,
- "document.createTextNode": true,
- "document.getElementById": true,
- "document.querySelectorAll": true,
- "location": true,
- "navigator": true,
- "open": true,
- "origin": true,
- "removeEventListener": true,
- "setInterval": true,
- "setTimeout": true
- },
- "packages": {
- "@swc/helpers>tslib": true,
- "@trezor/connect-web>@trezor/connect": true,
- "@trezor/connect-web>@trezor/connect-common": true,
- "@trezor/connect-web>@trezor/utils": true,
- "webpack>events": true
- }
- },
"@metamask/eth-trezor-keyring>hdkey": {
"packages": {
"browserify>assert": true,
@@ -1674,7 +1673,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1740,10 +1739,25 @@
"URL": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/keyring-api>@metamask/utils": true,
"@metamask/keyring-api>bech32": true,
- "@metamask/keyring-api>uuid": true,
- "@metamask/utils": true,
- "superstruct": true
+ "@metamask/keyring-api>uuid": true
+ }
+ },
+ "@metamask/keyring-api>@metamask/utils": {
+ "globals": {
+ "TextDecoder": true,
+ "TextEncoder": true
+ },
+ "packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
+ "@metamask/utils>@scure/base": true,
+ "@metamask/utils>pony-cause": true,
+ "@noble/hashes": true,
+ "browserify>buffer": true,
+ "nock>debug": true,
+ "semver": true
}
},
"@metamask/keyring-api>uuid": {
@@ -1801,7 +1815,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -1977,7 +1991,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2003,12 +2017,12 @@
"setTimeout": true
},
"packages": {
- "@metamask/eth-json-rpc-middleware": true,
"@metamask/eth-query": true,
"@metamask/eth-token-tracker>@metamask/eth-block-tracker": true,
"@metamask/network-controller>@metamask/base-controller": true,
"@metamask/network-controller>@metamask/controller-utils": true,
"@metamask/network-controller>@metamask/eth-json-rpc-infura": true,
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware": true,
"@metamask/network-controller>@metamask/eth-json-rpc-provider": true,
"@metamask/network-controller>@metamask/swappable-obj-proxy": true,
"@metamask/rpc-errors": true,
@@ -2050,7 +2064,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2064,13 +2078,19 @@
"setTimeout": true
},
"packages": {
- "@metamask/eth-json-rpc-middleware>@metamask/eth-json-rpc-provider": true,
+ "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": true,
"@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true,
"@metamask/rpc-errors": true,
"@metamask/utils": true,
"node-fetch": true
}
},
+ "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/eth-json-rpc-provider": {
+ "packages": {
+ "@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": true,
+ "@metamask/safe-event-emitter": true
+ }
+ },
"@metamask/network-controller>@metamask/eth-json-rpc-infura>@metamask/json-rpc-engine": {
"packages": {
"@metamask/rpc-errors": true,
@@ -2078,6 +2098,29 @@
"@metamask/utils": true
}
},
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware": {
+ "globals": {
+ "URL": true,
+ "console.error": true,
+ "setTimeout": true
+ },
+ "packages": {
+ "@metamask/eth-json-rpc-middleware>klona": true,
+ "@metamask/eth-json-rpc-middleware>safe-stable-stringify": true,
+ "@metamask/eth-sig-util": true,
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": true,
+ "@metamask/rpc-errors": true,
+ "@metamask/utils": true,
+ "pify": true
+ }
+ },
+ "@metamask/network-controller>@metamask/eth-json-rpc-middleware>@metamask/json-rpc-engine": {
+ "packages": {
+ "@metamask/rpc-errors": true,
+ "@metamask/safe-event-emitter": true,
+ "@metamask/utils": true
+ }
+ },
"@metamask/network-controller>@metamask/eth-json-rpc-provider": {
"packages": {
"@metamask/rpc-errors": true,
@@ -2165,7 +2208,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2404,7 +2447,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2595,7 +2638,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2782,7 +2825,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2808,7 +2851,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2856,7 +2899,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -2938,13 +2981,13 @@
"fetch": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/eth-snap-keyring>@metamask/snaps-utils>@metamask/slip44": true,
"@metamask/rpc-errors": true,
"@metamask/snaps-execution-environments>@metamask/snaps-utils>@metamask/permission-controller": true,
"@metamask/snaps-execution-environments>@metamask/utils": true,
"@metamask/snaps-sdk": true,
"@metamask/snaps-sdk>@metamask/key-tree": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils>cron-parser": true,
"@metamask/snaps-utils>fast-json-stable-stringify": true,
"@metamask/snaps-utils>fast-xml-parser": true,
@@ -3004,7 +3047,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3020,12 +3063,12 @@
},
"@metamask/snaps-rpc-methods": {
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/rpc-errors": true,
"@metamask/snaps-rpc-methods>@metamask/permission-controller": true,
"@metamask/snaps-rpc-methods>@metamask/utils": true,
"@metamask/snaps-sdk": true,
"@metamask/snaps-sdk>@metamask/key-tree": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils": true,
"@noble/hashes": true
}
@@ -3082,7 +3125,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3096,8 +3139,8 @@
"fetch": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/rpc-errors": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-sdk>@metamask/utils": true
}
},
@@ -3116,7 +3159,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3131,7 +3174,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3156,10 +3199,10 @@
"fetch": true
},
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/rpc-errors": true,
"@metamask/snaps-sdk": true,
"@metamask/snaps-sdk>@metamask/key-tree": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils>@metamask/permission-controller": true,
"@metamask/snaps-utils>@metamask/slip44": true,
"@metamask/snaps-utils>@metamask/utils": true,
@@ -3223,8 +3266,8 @@
},
"@metamask/snaps-utils>@metamask/snaps-registry": {
"packages": {
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/message-signing-snap>@noble/curves": true,
- "@metamask/snaps-sdk>@metamask/superstruct": true,
"@metamask/snaps-utils>@metamask/snaps-registry>@metamask/utils": true,
"@noble/hashes": true
}
@@ -3235,7 +3278,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3250,7 +3293,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3414,7 +3457,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3491,7 +3534,7 @@
"TextEncoder": true
},
"packages": {
- "@metamask/snaps-sdk>@metamask/superstruct": true,
+ "@metamask/abi-utils>@metamask/superstruct": true,
"@metamask/utils>@scure/base": true,
"@metamask/utils>pony-cause": true,
"@noble/hashes": true,
@@ -3894,19 +3937,28 @@
"globals": {
"AbortController": true,
"Intl.NumberFormat": true,
+ "clearInterval": true,
"clearTimeout": true,
"console.error": true,
"console.info": true,
"console.log": true,
"console.warn": true,
+ "setInterval": true,
"setTimeout": true
},
"packages": {
"@swc/helpers>tslib": true,
+ "@trezor/connect-web>@trezor/utils>bignumber.js": true,
"browserify>buffer": true,
"webpack>events": true
}
},
+ "@trezor/connect-web>@trezor/utils>bignumber.js": {
+ "globals": {
+ "crypto": true,
+ "define": true
+ }
+ },
"@welldone-software/why-did-you-render": {
"globals": {
"Element": true,
From 15841b49bab43ec3114cb1f5397cbd7608e5d949 Mon Sep 17 00:00:00 2001
From: Dan J Miller
Date: Mon, 9 Sep 2024 17:52:42 -0230
Subject: [PATCH 06/43] fix merge conflict resolution errors
---
app/scripts/constants/sentry-state.ts | 3 ---
test/e2e/accounts/snap-account-signatures.spec.ts | 3 ---
test/e2e/default-fixture.js | 1 -
test/e2e/fixture-builder.js | 1 -
.../errors-after-init-opt-in-background-state.json | 1 -
test/e2e/tests/metrics/wallet-created.spec.js | 1 +
.../creation-successful/creation-successful.js | 4 ++++
7 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/app/scripts/constants/sentry-state.ts b/app/scripts/constants/sentry-state.ts
index e56dbe287c55..b275dfcb7a8f 100644
--- a/app/scripts/constants/sentry-state.ts
+++ b/app/scripts/constants/sentry-state.ts
@@ -206,7 +206,6 @@ export const SENTRY_BACKGROUND_STATE = {
PreferencesController: {
advancedGasFee: true,
currentLocale: true,
- disabledRpcMethodPreferences: true,
dismissSeedBackUpReminder: true,
featureFlags: true,
forgottenPassword: true,
@@ -263,8 +262,6 @@ export const SENTRY_BACKGROUND_STATE = {
},
SelectedNetworkController: { domains: false },
SignatureController: {
- unapprovedMsgCount: true,
- unapprovedMsgs: false,
unapprovedPersonalMsgCount: true,
unapprovedPersonalMsgs: false,
unapprovedTypedMessages: false,
diff --git a/test/e2e/accounts/snap-account-signatures.spec.ts b/test/e2e/accounts/snap-account-signatures.spec.ts
index bef16f22a47c..536d8168b1a3 100644
--- a/test/e2e/accounts/snap-account-signatures.spec.ts
+++ b/test/e2e/accounts/snap-account-signatures.spec.ts
@@ -1,6 +1,5 @@
import { Suite } from 'mocha';
import {
- openDapp,
tempToggleSettingRedesignedConfirmations,
withFixtures,
} from '../helpers';
@@ -33,8 +32,6 @@ describe('Snap Account Signatures', function (this: Suite) {
await tempToggleSettingRedesignedConfirmations(driver);
- await openDapp(driver);
-
// Run all 5 signature types
const locatorIDs = [
'#personalSign',
diff --git a/test/e2e/default-fixture.js b/test/e2e/default-fixture.js
index 8891d1830eb5..d07ca3ab3b58 100644
--- a/test/e2e/default-fixture.js
+++ b/test/e2e/default-fixture.js
@@ -214,7 +214,6 @@ function defaultFixture(inputChainId = CHAIN_IDS.LOCALHOST) {
smartTransactionsOptInStatus: false,
useNativeCurrencyAsPrimaryCurrency: true,
petnamesEnabled: true,
- showTokenAutodetectModal: false,
isRedesignedConfirmationsDeveloperEnabled: false,
showConfirmationAdvancedDetails: false,
},
diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js
index 798b570c5a2d..cbccac2eab0d 100644
--- a/test/e2e/fixture-builder.js
+++ b/test/e2e/fixture-builder.js
@@ -87,7 +87,6 @@ function onboardingFixture() {
smartTransactionsOptInStatus: false,
useNativeCurrencyAsPrimaryCurrency: true,
petnamesEnabled: true,
- showTokenAutodetectModal: false,
isRedesignedConfirmationsDeveloperEnabled: false,
showConfirmationAdvancedDetails: false,
},
diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json
index 20663c4c52bc..7a4d6335dab5 100644
--- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json
+++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json
@@ -201,7 +201,6 @@
"smartTransactionsOptInStatus": false,
"useNativeCurrencyAsPrimaryCurrency": true,
"petnamesEnabled": true,
- "showTokenAutodetectModal": "boolean",
"redesignedConfirmationsEnabled": true,
"redesignedTransactionsEnabled": "boolean",
"isRedesignedConfirmationsDeveloperEnabled": "boolean"
diff --git a/test/e2e/tests/metrics/wallet-created.spec.js b/test/e2e/tests/metrics/wallet-created.spec.js
index 890ac9342a8a..bc07cfdeea75 100644
--- a/test/e2e/tests/metrics/wallet-created.spec.js
+++ b/test/e2e/tests/metrics/wallet-created.spec.js
@@ -88,6 +88,7 @@ describe('Wallet Created Events @no-mmi', function () {
chain_id: '0x539',
environment_type: 'fullscreen',
is_profile_syncing_enabled: null,
+ is_signed_in: false,
});
},
);
diff --git a/ui/pages/onboarding-flow/creation-successful/creation-successful.js b/ui/pages/onboarding-flow/creation-successful/creation-successful.js
index fab463e5b685..79321c7c5991 100644
--- a/ui/pages/onboarding-flow/creation-successful/creation-successful.js
+++ b/ui/pages/onboarding-flow/creation-successful/creation-successful.js
@@ -25,6 +25,7 @@ import {
import { MetaMetricsContext } from '../../../contexts/metametrics';
import { useCreateSession } from '../../../hooks/metamask-notifications/useCreateSession';
import { selectIsProfileSyncingEnabled } from '../../../selectors/metamask-notifications/profile-syncing';
+import { selectIsSignedIn } from '../../../selectors/metamask-notifications/authentication';
export default function CreationSuccessful() {
const history = useHistory();
@@ -36,6 +37,8 @@ export default function CreationSuccessful() {
const isProfileSyncingEnabled = useSelector(selectIsProfileSyncingEnabled);
+ const isSignedIn = useSelector(selectIsSignedIn);
+
return (
@@ -115,6 +118,7 @@ export default function CreationSuccessful() {
event: MetaMetricsEventName.OnboardingWalletCreationComplete,
properties: {
method: firstTimeFlowType,
+ is_signed_in: isSignedIn,
is_profile_syncing_enabled: isProfileSyncingEnabled,
},
});
From 0372aa7d1ddeb63fc2b8eb133cd6b45f202ea07e Mon Sep 17 00:00:00 2001
From: Dan J Miller
Date: Wed, 11 Sep 2024 10:16:32 -0230
Subject: [PATCH 07/43] temp
From c2b3dbc3d89b755b8d036c467f05e14f280e778e Mon Sep 17 00:00:00 2001
From: Dan J Miller
Date: Tue, 10 Sep 2024 12:00:31 -0230
Subject: [PATCH 08/43] fix: Ignore yarn audit warning for GHSA-9wv6-86v2-598j
(#27024)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
This addresses the following `yarn audit` failure:
```
└─ path-to-regexp
├─ ID: 1099496
├─ Issue: path-to-regexp outputs backtracking regular expressions
├─ URL: https://github.com/advisories/GHSA-9wv6-86v2-598j
├─ Severity: high
├─ Vulnerable Versions: >=0.2.0 <8.0.0
│
├─ Tree Versions
│ └─ 1.7.0
│
└─ Dependents
└─ react-router@npm:5.1.2 [12b72]
```
path-to-Regexp is used in two files within react-router v5.1.2:
`generatePath.js` and `matchPath.js`. In both cases, `path` and
`options` variables are passed to a `compilePath` function. Those are
then passed to `pathtoRegexp`. The variables passed to `pathtoRegexp`
are dependent on props or parameters passed to react-router components
and/or methods explictly from the metamask code. So this vulnerability
cannot be exploited by an external actor.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27024?quickstart=1)
## **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 Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
.yarnrc.yml | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/.yarnrc.yml b/.yarnrc.yml
index 252333917781..1522080c0561 100644
--- a/.yarnrc.yml
+++ b/.yarnrc.yml
@@ -43,6 +43,16 @@ npmAuditIgnoreAdvisories:
# not appear to be used.
- 1092461
+ # Issue: path-to-regexp outputs backtracking regular expressions
+ # URL: https://github.com/advisories/GHSA-9wv6-86v2-598j
+ # path-to-regexp is used in react-router v5.1.2, which we use. However, the
+ # vulnerability in path-to-regexp could only be exploited within react-router
+ # if malicious properties were passed to react-router components or methods
+ # explicitly from our code. As such, this vulneratibility cannot be exploited
+ # by an external / malicious actor. Meanwhile, once we update to v6+,
+ # path-to-regexp will no longer be used.
+ - 1099499
+
# Temp fix for https://github.com/MetaMask/metamask-extension/pull/16920 for the sake of 11.7.1 hotfix
# This will be removed in this ticket https://github.com/MetaMask/metamask-extension/issues/22299
- 'ts-custom-error (deprecation)'
From 856f1f942be124663ff7bde9a6394e03cc6ed0eb Mon Sep 17 00:00:00 2001
From: Dan J Miller
Date: Tue, 10 Sep 2024 14:22:45 -0230
Subject: [PATCH 09/43] fix: Add a second id to ignore for the
GHSA-9wv6-86v2-598j (#27041)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Follow up to https://github.com/MetaMask/metamask-extension/pull/27024.
Since that was merged, an update was made to
https://github.com/MetaMask/metamask-extension/pull/27024, and so the
yarn audit warning now has a new id, which we need to include in the
`npmAuditIgnoreAdvisories` config.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27041?quickstart=1)
## **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 Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
.yarnrc.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.yarnrc.yml b/.yarnrc.yml
index 1522080c0561..63b9539cbfba 100644
--- a/.yarnrc.yml
+++ b/.yarnrc.yml
@@ -52,6 +52,7 @@ npmAuditIgnoreAdvisories:
# by an external / malicious actor. Meanwhile, once we update to v6+,
# path-to-regexp will no longer be used.
- 1099499
+ - 1099514
# Temp fix for https://github.com/MetaMask/metamask-extension/pull/16920 for the sake of 11.7.1 hotfix
# This will be removed in this ticket https://github.com/MetaMask/metamask-extension/issues/22299
From e0deec9b2127f988212b41e6a5fc72412cab7b21 Mon Sep 17 00:00:00 2001
From: Dan J Miller
Date: Tue, 10 Sep 2024 15:32:12 -0230
Subject: [PATCH 10/43] fix: Update id for ignoring path-to-regexp advisory
(#27044)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Follow up to https://github.com/MetaMask/metamask-extension/pull/27024
and https://github.com/MetaMask/metamask-extension/pull/27041
The id has changed again, so we are going to try updating one more time.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27044?quickstart=1)
## **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 Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
.yarnrc.yml | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/.yarnrc.yml b/.yarnrc.yml
index 63b9539cbfba..5d4aa7cd4e73 100644
--- a/.yarnrc.yml
+++ b/.yarnrc.yml
@@ -51,8 +51,7 @@ npmAuditIgnoreAdvisories:
# explicitly from our code. As such, this vulneratibility cannot be exploited
# by an external / malicious actor. Meanwhile, once we update to v6+,
# path-to-regexp will no longer be used.
- - 1099499
- - 1099514
+ - 1099518
# Temp fix for https://github.com/MetaMask/metamask-extension/pull/16920 for the sake of 11.7.1 hotfix
# This will be removed in this ticket https://github.com/MetaMask/metamask-extension/issues/22299
From 75fed5256044abc60fb929371424b863ac9d74cd Mon Sep 17 00:00:00 2001
From: MetaMask Bot
Date: Wed, 11 Sep 2024 15:37:07 +0000
Subject: [PATCH 11/43] Version v12.2.3
---
CHANGELOG.md | 5 ++++-
package.json | 2 +-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b6d7f827ca85..58113296a846 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [12.2.3]
+
## [12.2.2]
### Fixed
- This build was needed to fix release publishing on our master branch. It also includes the addition of the missing v12.2.0 changelog. Functionality and code is equivalent to v12.2.0.
@@ -5044,7 +5046,8 @@ Update styles and spacing on the critical error page ([#20350](https://github.c
- Added the ability to restore accounts from seed words.
-[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v12.2.2...HEAD
+[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v12.2.3...HEAD
+[12.2.3]: https://github.com/MetaMask/metamask-extension/compare/v12.2.2...v12.2.3
[12.2.2]: https://github.com/MetaMask/metamask-extension/compare/v12.2.1...v12.2.2
[12.2.1]: https://github.com/MetaMask/metamask-extension/compare/v12.2.0...v12.2.1
[12.2.0]: https://github.com/MetaMask/metamask-extension/compare/v12.1.3...v12.2.0
diff --git a/package.json b/package.json
index 174a929240c4..f04c060bd55b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "metamask-crx",
- "version": "12.2.2",
+ "version": "12.2.3",
"private": true,
"repository": {
"type": "git",
From 439f7d6a60dcd956271f0b228d878e222c454d33 Mon Sep 17 00:00:00 2001
From: Charly Chevalier
Date: Fri, 6 Sep 2024 18:06:01 +0200
Subject: [PATCH 12/43] test(btc): mock ramps endpoints (#26941)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Follow-up of:
- https://github.com/MetaMask/metamask-extension/pull/26929
The previous PR did unblock the CI quickly but relying on a external
network call might still have side-effects, thus it's preferable to hook
all network calls.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/26941?quickstart=1)
Relates to:
- https://github.com/MetaMask/metamask-extension/pull/26929
1. `yarn build:test:flask`
2. `yarn test:e2e:single
test/e2e/flask/btc/btc-account-overview.spec.ts`
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
- [ ] 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.
---
.../flask/btc/btc-account-overview.spec.ts | 4 +-
test/e2e/flask/btc/common-btc.ts | 57 +++++++++++++++----
2 files changed, 46 insertions(+), 15 deletions(-)
diff --git a/test/e2e/flask/btc/btc-account-overview.spec.ts b/test/e2e/flask/btc/btc-account-overview.spec.ts
index 1ec530b5b64c..070a87c5bd6e 100644
--- a/test/e2e/flask/btc/btc-account-overview.spec.ts
+++ b/test/e2e/flask/btc/btc-account-overview.spec.ts
@@ -33,9 +33,7 @@ describe('BTC Account - Overview', function (this: Suite) {
const buySellButton = await driver.waitForSelector(
'[data-testid="coin-overview-buy"]',
);
- // Ramps now support buyable chains dynamically (https://github.com/MetaMask/metamask-extension/pull/24041), for now it's
- // disabled for Bitcoin
- assert.equal(await buySellButton.isEnabled(), false);
+ assert.equal(await buySellButton.isEnabled(), true);
const portfolioButton = await driver.waitForSelector(
'[data-testid="coin-overview-portfolio"]',
diff --git a/test/e2e/flask/btc/common-btc.ts b/test/e2e/flask/btc/common-btc.ts
index 0bcf1663b501..a33ab1241a1c 100644
--- a/test/e2e/flask/btc/common-btc.ts
+++ b/test/e2e/flask/btc/common-btc.ts
@@ -2,6 +2,7 @@ import { Mockttp } from 'mockttp';
import FixtureBuilder from '../../fixture-builder';
import { withFixtures, unlockWallet } from '../../helpers';
import { DEFAULT_BTC_ACCOUNT } from '../../constants';
+import { MultichainNetworks } from '../../../../shared/constants/multichain/networks';
import { Driver } from '../../webdriver/driver';
import { createBtcAccount } from '../../accounts/common';
@@ -19,17 +20,43 @@ export async function mockBtcBalanceQuote(
mockServer: Mockttp,
address: string = DEFAULT_BTC_ACCOUNT,
) {
- return [
- await mockServer
- .forGet(/https:\/\/api\.blockchair\.com\/bitcoin\/addresses\/balances/u)
- .withQuery({
- addresses: address,
- })
- .thenCallback(() => ({
- statusCode: 200,
- json: GENERATE_MOCK_BTC_BALANCE_CALL(address),
- })),
- ];
+ return await mockServer
+ .forGet(/https:\/\/api\.blockchair\.com\/bitcoin\/addresses\/balances/u)
+ .withQuery({
+ addresses: address,
+ })
+ .thenCallback(() => ({
+ statusCode: 200,
+ json: GENERATE_MOCK_BTC_BALANCE_CALL(address),
+ }));
+}
+
+export async function mockRampsDynamicFeatureFlag(
+ mockServer: Mockttp,
+ subDomain: string,
+) {
+ return await mockServer
+ .forGet(
+ `https://on-ramp-content.${subDomain}.cx.metamask.io/regions/networks`,
+ )
+ .withQuery({
+ context: 'extension',
+ })
+ .thenCallback(() => ({
+ statusCode: 200,
+ json: {
+ networks: [
+ {
+ active: true,
+ chainId: MultichainNetworks.BITCOIN,
+ chainName: 'Bitcoin',
+ shortName: 'Bitcoin',
+ nativeTokenSupported: true,
+ isEvm: false,
+ },
+ ],
+ },
+ }));
}
export async function withBtcAccountSnap(
@@ -48,7 +75,13 @@ export async function withBtcAccountSnap(
.build(),
title,
dapp: true,
- testSpecificMock: mockBtcBalanceQuote,
+ testSpecificMock: async (mockServer: Mockttp) => [
+ await mockBtcBalanceQuote(mockServer),
+ // See: PROD_RAMP_API_BASE_URL
+ await mockRampsDynamicFeatureFlag(mockServer, 'api'),
+ // See: UAT_RAMP_API_BASE_URL
+ await mockRampsDynamicFeatureFlag(mockServer, 'uat-api'),
+ ],
},
async ({ driver }: { driver: Driver }) => {
await unlockWallet(driver);
From 5eaa9d312684e40ca2fae9625a45668a505de81b Mon Sep 17 00:00:00 2001
From: Jyoti Puri
Date: Wed, 11 Sep 2024 22:28:10 +0530
Subject: [PATCH 13/43] fix (cherry-pick): Adding patch on
eth-json-rpc-middleware to disable verifyContract field validation for cosmos
(#27065)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Cherry-picks https://github.com/MetaMask/metamask-extension/pull/27021
(https://github.com/MetaMask/metamask-extension/commit/4ee09fc71ff5915f3b4b64173d98312c913bf7f4)
## **Description**
Adding patch on eth-json-rpc-middleware to disable verifyContract field
validation for cosmos
## **Related issues**
Fixes: https://github.com/MetaMask/metamask-extension/issues/26980
## **Manual testing steps**
1. Submit a types signature request with verifyingContract set to
`cosmos`
2. Ensure that you are able to sign it
## **Screenshots/Recordings**
## **Pre-merge author checklist**
- [X] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [X] I've completed the PR template to the best of my ability
- [X] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [X] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
...rpc-middleware-npm-14.0.1-b6c2ccbe8c.patch | 13 ++++++
package.json | 2 +-
yarn.lock | 41 ++++++++++++++-----
3 files changed, 44 insertions(+), 12 deletions(-)
create mode 100644 .yarn/patches/@metamask-eth-json-rpc-middleware-npm-14.0.1-b6c2ccbe8c.patch
diff --git a/.yarn/patches/@metamask-eth-json-rpc-middleware-npm-14.0.1-b6c2ccbe8c.patch b/.yarn/patches/@metamask-eth-json-rpc-middleware-npm-14.0.1-b6c2ccbe8c.patch
new file mode 100644
index 000000000000..e82feb182c3a
--- /dev/null
+++ b/.yarn/patches/@metamask-eth-json-rpc-middleware-npm-14.0.1-b6c2ccbe8c.patch
@@ -0,0 +1,13 @@
+diff --git a/dist/wallet.js b/dist/wallet.js
+index fce8272ab926443df4c5971c811664f849791425..9237ffcaaea2260e01182feecec667b10edd35a0 100644
+--- a/dist/wallet.js
++++ b/dist/wallet.js
+@@ -293,7 +293,7 @@ exports.createWalletMiddleware = createWalletMiddleware;
+ */
+ function validateVerifyingContract(data) {
+ const { domain: { verifyingContract } = {} } = (0, normalize_1.parseTypedMessage)(data);
+- if (verifyingContract && !(0, utils_1.isValidHexAddress)(verifyingContract)) {
++ if (verifyingContract && verifyingContract !== 'cosmos' && !(0, utils_1.isValidHexAddress)(verifyingContract)) {
+ throw rpc_errors_1.rpcErrors.invalidInput();
+ }
+ }
diff --git a/package.json b/package.json
index f04c060bd55b..541a6a7bba82 100644
--- a/package.json
+++ b/package.json
@@ -303,7 +303,7 @@
"@metamask/design-tokens": "^4.0.0",
"@metamask/ens-controller": "^10.0.1",
"@metamask/eth-json-rpc-filters": "^7.0.0",
- "@metamask/eth-json-rpc-middleware": "^14.0.1",
+ "@metamask/eth-json-rpc-middleware": "patch:@metamask/eth-json-rpc-middleware@npm%3A14.0.1#~/.yarn/patches/@metamask-eth-json-rpc-middleware-npm-14.0.1-b6c2ccbe8c.patch",
"@metamask/eth-ledger-bridge-keyring": "patch:@metamask/eth-ledger-bridge-keyring@npm%3A2.0.1#~/.yarn/patches/@metamask-eth-ledger-bridge-keyring-npm-2.0.1-7a5d815b2d.patch",
"@metamask/eth-query": "^4.0.0",
"@metamask/eth-sig-util": "^7.0.1",
diff --git a/yarn.lock b/yarn.lock
index 41d26bdef14e..bd7c41b54bb8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5036,7 +5036,7 @@ __metadata:
languageName: node
linkType: hard
-"@metamask/eth-block-tracker@npm:^9.0.2":
+"@metamask/eth-block-tracker@npm:^9.0.2, @metamask/eth-block-tracker@npm:^9.0.3":
version: 9.0.3
resolution: "@metamask/eth-block-tracker@npm:9.0.3"
dependencies:
@@ -5088,26 +5088,45 @@ __metadata:
languageName: node
linkType: hard
+"@metamask/eth-json-rpc-middleware@npm:14.0.1":
+ version: 14.0.1
+ resolution: "@metamask/eth-json-rpc-middleware@npm:14.0.1"
+ dependencies:
+ "@metamask/eth-block-tracker": "npm:^11.0.1"
+ "@metamask/eth-json-rpc-provider": "npm:^4.1.1"
+ "@metamask/eth-sig-util": "npm:^7.0.3"
+ "@metamask/json-rpc-engine": "npm:^9.0.2"
+ "@metamask/rpc-errors": "npm:^6.3.1"
+ "@metamask/utils": "npm:^9.1.0"
+ "@types/bn.js": "npm:^5.1.5"
+ bn.js: "npm:^5.2.1"
+ klona: "npm:^2.0.6"
+ pify: "npm:^5.0.0"
+ safe-stable-stringify: "npm:^2.4.3"
+ checksum: 10/39beecb0d2be19854b132fd615aee1f29195602d3db902f52755260b26a2c37c0a91cd635a09d4dc16f922d32bb229003b338228ae29577c5151d880fad04637
+ languageName: node
+ linkType: hard
+
"@metamask/eth-json-rpc-middleware@npm:^12.1.1":
- version: 12.1.1
- resolution: "@metamask/eth-json-rpc-middleware@npm:12.1.1"
+ version: 12.1.2
+ resolution: "@metamask/eth-json-rpc-middleware@npm:12.1.2"
dependencies:
- "@metamask/eth-block-tracker": "npm:^9.0.2"
- "@metamask/eth-json-rpc-provider": "npm:^2.1.0"
+ "@metamask/eth-block-tracker": "npm:^9.0.3"
+ "@metamask/eth-json-rpc-provider": "npm:^3.0.2"
"@metamask/eth-sig-util": "npm:^7.0.0"
- "@metamask/json-rpc-engine": "npm:^7.1.1"
+ "@metamask/json-rpc-engine": "npm:^8.0.2"
"@metamask/rpc-errors": "npm:^6.0.0"
"@metamask/utils": "npm:^8.1.0"
klona: "npm:^2.0.6"
pify: "npm:^5.0.0"
safe-stable-stringify: "npm:^2.4.3"
- checksum: 10/0018da198a4f8fbdeab25aa8184377b3215e365b2a631d0f8d7f0577e281c860a1d19fc58ad310afb6d005291c0797dabfe14bdb4adb16300c7f28b11fb26cbc
+ checksum: 10/1c0f186a35765394a28695bcade84c636b0c92cf3252219d1e9cbdd31231ad09fea5ec7bff7d31e2c7fe4d2158f15b54a5e42166549b69af1f7e475a1c7ae536
languageName: node
linkType: hard
-"@metamask/eth-json-rpc-middleware@npm:^14.0.1":
+"@metamask/eth-json-rpc-middleware@patch:@metamask/eth-json-rpc-middleware@npm%3A14.0.1#~/.yarn/patches/@metamask-eth-json-rpc-middleware-npm-14.0.1-b6c2ccbe8c.patch":
version: 14.0.1
- resolution: "@metamask/eth-json-rpc-middleware@npm:14.0.1"
+ resolution: "@metamask/eth-json-rpc-middleware@patch:@metamask/eth-json-rpc-middleware@npm%3A14.0.1#~/.yarn/patches/@metamask-eth-json-rpc-middleware-npm-14.0.1-b6c2ccbe8c.patch::version=14.0.1&hash=96e7e0"
dependencies:
"@metamask/eth-block-tracker": "npm:^11.0.1"
"@metamask/eth-json-rpc-provider": "npm:^4.1.1"
@@ -5120,7 +5139,7 @@ __metadata:
klona: "npm:^2.0.6"
pify: "npm:^5.0.0"
safe-stable-stringify: "npm:^2.4.3"
- checksum: 10/39beecb0d2be19854b132fd615aee1f29195602d3db902f52755260b26a2c37c0a91cd635a09d4dc16f922d32bb229003b338228ae29577c5151d880fad04637
+ checksum: 10/d1d97a845a8a9a5931c3853c6e2768a97ba289d676a2a8b6111077531943f9647430ef8e3f2a05f4643760ffdab1af0dc72574ca3010feadbdfab3dec345b7c8
languageName: node
linkType: hard
@@ -25272,7 +25291,7 @@ __metadata:
"@metamask/eslint-config-typescript": "npm:^9.0.1"
"@metamask/eslint-plugin-design-tokens": "npm:^1.1.0"
"@metamask/eth-json-rpc-filters": "npm:^7.0.0"
- "@metamask/eth-json-rpc-middleware": "npm:^14.0.1"
+ "@metamask/eth-json-rpc-middleware": "patch:@metamask/eth-json-rpc-middleware@npm%3A14.0.1#~/.yarn/patches/@metamask-eth-json-rpc-middleware-npm-14.0.1-b6c2ccbe8c.patch"
"@metamask/eth-ledger-bridge-keyring": "patch:@metamask/eth-ledger-bridge-keyring@npm%3A2.0.1#~/.yarn/patches/@metamask-eth-ledger-bridge-keyring-npm-2.0.1-7a5d815b2d.patch"
"@metamask/eth-query": "npm:^4.0.0"
"@metamask/eth-sig-util": "npm:^7.0.1"
From 36118362c0ab59802ef9f749d412451650d65188 Mon Sep 17 00:00:00 2001
From: Dan J Miller
Date: Wed, 11 Sep 2024 14:32:32 -0230
Subject: [PATCH 14/43] v12.2.3 changelog (#27073)
Updates the changelog for v12.2.3
---
CHANGELOG.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 58113296a846..ad00f06ec372 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [12.2.3]
+### Fixed
+- Fixes dapps integrating with the cosmos chain that rely on setting the `verifyingContract` field of a signature to `"cosmos"`
## [12.2.2]
### Fixed
From fc9b12ae55946b6f6d0a28218e2035dec62aa85d Mon Sep 17 00:00:00 2001
From: Dan J Miller
Date: Wed, 11 Sep 2024 15:47:51 -0230
Subject: [PATCH 15/43] Temporary patch to changelog to get v12.3.0 RC build
passing (#27075)
Temporary patch to changelog to get v12.3.0 RC build passing
---
CHANGELOG.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9eac7f92132e..effd41bb7b8f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [12.3.0]
-### Uncategorized
+### Fixed
- Merge branch 'Version-v12.2.0' into Version-v12.3.0
- Merge remote-tracking branch 'origin/master' into Version-v12.2.0
- CherryPick: "fix: issue where `wallet_addEtherumChain` was incorrectly enforcing inclusion of a blockExplorerUrls property which is not required (#26938)" ([#26938](https://github.com/MetaMask/metamask-extension/pull/26938))
From 6d3a56aebc52c27005bc0b923ed5a7fdb28a251b Mon Sep 17 00:00:00 2001
From: Brian Bergeron
Date: Fri, 13 Sep 2024 08:04:51 -0700
Subject: [PATCH 16/43] feat(migration): enable token auto-detection when basic
functionality is on (#27110)
Cherry picks https://github.com/MetaMask/metamask-extension/pull/26406
to 12.3.0
Co-authored-by: sahar-fehri
---
app/scripts/migrations/125.1.test.ts | 107 ++++++++++++++++++
app/scripts/migrations/125.1.ts | 50 ++++++++
app/scripts/migrations/index.js | 1 +
...rs-after-init-opt-in-background-state.json | 2 +-
.../errors-after-init-opt-in-ui-state.json | 2 +-
.../multichain/asset-picker-send.spec.ts | 13 ++-
6 files changed, 171 insertions(+), 4 deletions(-)
create mode 100644 app/scripts/migrations/125.1.test.ts
create mode 100644 app/scripts/migrations/125.1.ts
diff --git a/app/scripts/migrations/125.1.test.ts b/app/scripts/migrations/125.1.test.ts
new file mode 100644
index 000000000000..eb00db9d1e07
--- /dev/null
+++ b/app/scripts/migrations/125.1.test.ts
@@ -0,0 +1,107 @@
+import { migrate, version } from './125.1';
+
+const oldVersion = 125;
+
+describe(`migration #${version}`, () => {
+ afterEach(() => jest.resetAllMocks());
+
+ it('updates the version metadata', async () => {
+ const oldStorage = {
+ meta: { version: oldVersion },
+ data: {},
+ };
+
+ const newStorage = await migrate(oldStorage);
+ expect(newStorage.meta).toStrictEqual({ version });
+ });
+
+ it('Gracefully handles empty/undefined PreferencesController', async () => {
+ for (const PreferencesController of [{}, undefined, null, 1, '', []]) {
+ const oldStorage = {
+ meta: { version: oldVersion },
+ data: { PreferencesController },
+ };
+
+ const newStorage = await migrate(oldStorage);
+ expect(newStorage.data.TxController).toStrictEqual(undefined);
+ }
+ });
+
+ it('Enables token autodetection when basic functionality is on', async () => {
+ const oldStorage = {
+ meta: { version: oldVersion },
+ data: {
+ PreferencesController: {
+ useExternalServices: true,
+ },
+ },
+ };
+
+ const newStorage = await migrate(oldStorage);
+ expect(newStorage.data).toEqual({
+ PreferencesController: {
+ useExternalServices: true,
+ useTokenDetection: true,
+ },
+ });
+ });
+
+ it('Does not enable token autodetection when basic functionality is off', async () => {
+ const oldStorage = {
+ meta: { version: oldVersion },
+ data: {
+ PreferencesController: {
+ useExternalServices: false,
+ },
+ },
+ };
+
+ const newStorage = await migrate(oldStorage);
+ expect(newStorage.data).toEqual({
+ PreferencesController: {
+ useExternalServices: false,
+ },
+ });
+ });
+
+ it('Removes showTokenAutodetectModalOnUpgrade from the app metadata controller', async () => {
+ const oldStorage = {
+ meta: { version: oldVersion },
+ data: {
+ AppMetadataController: {
+ previousMigrationVersion: oldVersion,
+ currentMigrationVersion: version,
+ showTokenAutodetectModalOnUpgrade: null,
+ },
+ },
+ };
+
+ const newStorage = await migrate(oldStorage);
+ expect(newStorage.data).toEqual({
+ AppMetadataController: {
+ previousMigrationVersion: oldVersion,
+ currentMigrationVersion: version,
+ },
+ });
+ });
+
+ it('Does nothing if showTokenAutodetectModalOnUpgrade is not in the app metadata controller', async () => {
+ const oldStorage = {
+ meta: { version: oldVersion },
+ data: {
+ AppMetadataController: {
+ previousMigrationVersion: oldVersion,
+ currentMigrationVersion: version,
+ },
+ },
+ };
+
+ const newStorage = await migrate(oldStorage);
+ expect(newStorage.data).toEqual({
+ AppMetadataController: {
+ previousMigrationVersion: oldVersion,
+ currentMigrationVersion: version,
+ },
+ });
+ });
+});
diff --git a/app/scripts/migrations/125.1.ts b/app/scripts/migrations/125.1.ts
new file mode 100644
index 000000000000..d3c975a78a11
--- /dev/null
+++ b/app/scripts/migrations/125.1.ts
@@ -0,0 +1,50 @@
+import { hasProperty, isObject } from '@metamask/utils';
+import { cloneDeep } from 'lodash';
+
+type VersionedData = {
+ meta: { version: number };
+ data: Record;
+};
+
+export const version = 125.1;
+
+/**
+ * This migration enables token auto-detection if the basic functionality toggle is on.
+ *
+ * It also removes an unused property `showTokenAutodetectModalOnUpgrade` from the app metadata controller.
+ *
+ * @param originalVersionedData - Versioned MetaMask extension state, exactly
+ * what we persist to dist.
+ * @param originalVersionedData.meta - State metadata.
+ * @param originalVersionedData.meta.version - The current state version.
+ * @param originalVersionedData.data - The persisted MetaMask state, keyed by
+ * controller.
+ * @returns Updated versioned MetaMask extension state.
+ */
+export async function migrate(
+ originalVersionedData: VersionedData,
+): Promise {
+ const versionedData = cloneDeep(originalVersionedData);
+ versionedData.meta.version = version;
+ transformState(versionedData.data);
+ return versionedData;
+}
+
+function transformState(state: Record) {
+ if (
+ hasProperty(state, 'PreferencesController') &&
+ isObject(state.PreferencesController) &&
+ state.PreferencesController.useExternalServices === true
+ ) {
+ state.PreferencesController.useTokenDetection = true;
+ }
+
+ if (
+ hasProperty(state, 'AppMetadataController') &&
+ isObject(state.AppMetadataController)
+ ) {
+ delete state.AppMetadataController.showTokenAutodetectModalOnUpgrade;
+ }
+
+ return state;
+}
diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js
index 0146779d408f..bb64ec957f75 100644
--- a/app/scripts/migrations/index.js
+++ b/app/scripts/migrations/index.js
@@ -144,6 +144,7 @@ const migrations = [
require('./123'),
require('./124'),
require('./125'),
+ require('./125.1'),
];
export default migrations;
diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json
index 7a4d6335dab5..2d2c362b30f8 100644
--- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json
+++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-background-state.json
@@ -175,7 +175,7 @@
"dismissSeedBackUpReminder": true,
"useMultiAccountBalanceChecker": true,
"useSafeChainsListValidation": "boolean",
- "useTokenDetection": false,
+ "useTokenDetection": true,
"useNftDetection": false,
"use4ByteResolution": true,
"useCurrencyRateCheck": true,
diff --git a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json
index c74b7f35c85d..d5ff2eecc5eb 100644
--- a/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json
+++ b/test/e2e/tests/metrics/state-snapshots/errors-after-init-opt-in-ui-state.json
@@ -109,7 +109,7 @@
"dismissSeedBackUpReminder": true,
"useMultiAccountBalanceChecker": true,
"useSafeChainsListValidation": true,
- "useTokenDetection": false,
+ "useTokenDetection": true,
"useNftDetection": false,
"useCurrencyRateCheck": true,
"useRequestQueue": true,
diff --git a/test/e2e/tests/multichain/asset-picker-send.spec.ts b/test/e2e/tests/multichain/asset-picker-send.spec.ts
index 8358e8242f69..5accb14c6074 100644
--- a/test/e2e/tests/multichain/asset-picker-send.spec.ts
+++ b/test/e2e/tests/multichain/asset-picker-send.spec.ts
@@ -34,6 +34,15 @@ describe('AssetPickerSendFlow @no-mmi', function () {
async ({ driver }: { driver: Driver }) => {
await unlockWallet(driver);
+ // Disable token auto detection
+ await driver.openNewURL(
+ `${driver.extensionUrl}/home.html#settings/security`,
+ );
+ await driver.clickElement(
+ '[data-testid="autoDetectTokens"] .toggle-button',
+ );
+ await driver.navigate();
+
// Open the send flow
openActionMenuAndStartSendFlow(driver);
@@ -72,13 +81,13 @@ describe('AssetPickerSendFlow @no-mmi', function () {
assert.equal(tokenListSecondaryValue, '$250,000.00');
- // Search for BNB
+ // Search for CHZ
const searchInputField = await driver.waitForSelector(
'[data-testid="asset-picker-modal-search-input"]',
);
await searchInputField.sendKeys('CHZ');
- // check that BNB is disabled
+ // check that CHZ is disabled
const [, tkn] = await driver.findElements(
'[data-testid="multichain-token-list-button"]',
);
From 88b8ef114551b69ad37b39ef7bed048c7241cc41 Mon Sep 17 00:00:00 2001
From: Charly Chevalier
Date: Mon, 16 Sep 2024 17:14:20 +0200
Subject: [PATCH 17/43] fix(cherry-pick): resolve path-to-regexp to v1.9.0 to
resolve GHSA-9wv6-86v2-598j (#27113) (#27159)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
This permanently fixes https://github.com/advisories/GHSA-9wv6-86v2-598j
by resolving that package to a recently released version that does not
having breaking changes and where the security vulnerability is
resolved.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27159?quickstart=1)
## **Related issues**
Fixes:
- https://github.com/advisories/GHSA-9wv6-86v2-598j
## **Manual testing steps**
N/A
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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: Dan J Miller
Co-authored-by: MetaMask Bot
---
.yarnrc.yml | 10 ----------
lavamoat/browserify/beta/policy.json | 6 +++---
lavamoat/browserify/flask/policy.json | 6 +++---
lavamoat/browserify/main/policy.json | 6 +++---
lavamoat/browserify/mmi/policy.json | 6 +++---
package.json | 3 ++-
yarn.lock | 22 ++++------------------
7 files changed, 18 insertions(+), 41 deletions(-)
diff --git a/.yarnrc.yml b/.yarnrc.yml
index 5d4aa7cd4e73..252333917781 100644
--- a/.yarnrc.yml
+++ b/.yarnrc.yml
@@ -43,16 +43,6 @@ npmAuditIgnoreAdvisories:
# not appear to be used.
- 1092461
- # Issue: path-to-regexp outputs backtracking regular expressions
- # URL: https://github.com/advisories/GHSA-9wv6-86v2-598j
- # path-to-regexp is used in react-router v5.1.2, which we use. However, the
- # vulnerability in path-to-regexp could only be exploited within react-router
- # if malicious properties were passed to react-router components or methods
- # explicitly from our code. As such, this vulneratibility cannot be exploited
- # by an external / malicious actor. Meanwhile, once we update to v6+,
- # path-to-regexp will no longer be used.
- - 1099518
-
# Temp fix for https://github.com/MetaMask/metamask-extension/pull/16920 for the sake of 11.7.1 hotfix
# This will be removed in this ticket https://github.com/MetaMask/metamask-extension/issues/22299
- 'ts-custom-error (deprecation)'
diff --git a/lavamoat/browserify/beta/policy.json b/lavamoat/browserify/beta/policy.json
index eb3caba43c21..605c88c89ea1 100644
--- a/lavamoat/browserify/beta/policy.json
+++ b/lavamoat/browserify/beta/policy.json
@@ -5552,7 +5552,7 @@
"react-router-dom>react-router>mini-create-react-context": true,
"react-router-dom>tiny-invariant": true,
"react-router-dom>tiny-warning": true,
- "sinon>nise>path-to-regexp": true
+ "serve-handler>path-to-regexp": true
}
},
"react-router-dom>react-router>history": {
@@ -5702,9 +5702,9 @@
"process": true
}
},
- "sinon>nise>path-to-regexp": {
+ "serve-handler>path-to-regexp": {
"packages": {
- "sinon>nise>path-to-regexp>isarray": true
+ "serve-handler>path-to-regexp>isarray": true
}
},
"stream-browserify": {
diff --git a/lavamoat/browserify/flask/policy.json b/lavamoat/browserify/flask/policy.json
index eb3caba43c21..605c88c89ea1 100644
--- a/lavamoat/browserify/flask/policy.json
+++ b/lavamoat/browserify/flask/policy.json
@@ -5552,7 +5552,7 @@
"react-router-dom>react-router>mini-create-react-context": true,
"react-router-dom>tiny-invariant": true,
"react-router-dom>tiny-warning": true,
- "sinon>nise>path-to-regexp": true
+ "serve-handler>path-to-regexp": true
}
},
"react-router-dom>react-router>history": {
@@ -5702,9 +5702,9 @@
"process": true
}
},
- "sinon>nise>path-to-regexp": {
+ "serve-handler>path-to-regexp": {
"packages": {
- "sinon>nise>path-to-regexp>isarray": true
+ "serve-handler>path-to-regexp>isarray": true
}
},
"stream-browserify": {
diff --git a/lavamoat/browserify/main/policy.json b/lavamoat/browserify/main/policy.json
index eb3caba43c21..605c88c89ea1 100644
--- a/lavamoat/browserify/main/policy.json
+++ b/lavamoat/browserify/main/policy.json
@@ -5552,7 +5552,7 @@
"react-router-dom>react-router>mini-create-react-context": true,
"react-router-dom>tiny-invariant": true,
"react-router-dom>tiny-warning": true,
- "sinon>nise>path-to-regexp": true
+ "serve-handler>path-to-regexp": true
}
},
"react-router-dom>react-router>history": {
@@ -5702,9 +5702,9 @@
"process": true
}
},
- "sinon>nise>path-to-regexp": {
+ "serve-handler>path-to-regexp": {
"packages": {
- "sinon>nise>path-to-regexp>isarray": true
+ "serve-handler>path-to-regexp>isarray": true
}
},
"stream-browserify": {
diff --git a/lavamoat/browserify/mmi/policy.json b/lavamoat/browserify/mmi/policy.json
index 465b5dcf621b..96ba8b467983 100644
--- a/lavamoat/browserify/mmi/policy.json
+++ b/lavamoat/browserify/mmi/policy.json
@@ -5620,7 +5620,7 @@
"react-router-dom>react-router>mini-create-react-context": true,
"react-router-dom>tiny-invariant": true,
"react-router-dom>tiny-warning": true,
- "sinon>nise>path-to-regexp": true
+ "serve-handler>path-to-regexp": true
}
},
"react-router-dom>react-router>history": {
@@ -5770,9 +5770,9 @@
"process": true
}
},
- "sinon>nise>path-to-regexp": {
+ "serve-handler>path-to-regexp": {
"packages": {
- "sinon>nise>path-to-regexp>isarray": true
+ "serve-handler>path-to-regexp>isarray": true
}
},
"stream-browserify": {
diff --git a/package.json b/package.json
index be00bf7c6c65..c95b55be0b83 100644
--- a/package.json
+++ b/package.json
@@ -265,7 +265,8 @@
"@metamask/snaps-controllers@npm:^9.4.0": "patch:@metamask/snaps-controllers@npm%3A9.4.0#~/.yarn/patches/@metamask-snaps-controllers-npm-9.4.0-7c3abbbea6.patch",
"@metamask/nonce-tracker@npm:^5.0.0": "patch:@metamask/nonce-tracker@npm%3A5.0.0#~/.yarn/patches/@metamask-nonce-tracker-npm-5.0.0-d81478218e.patch",
"@metamask/keyring-controller@npm:^17.1.0": "patch:@metamask/keyring-controller@npm%3A17.1.1#~/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch",
- "@trezor/connect-web@npm:^9.1.11": "patch:@trezor/connect-web@npm%3A9.3.0#~/.yarn/patches/@trezor-connect-web-npm-9.3.0-040ab10d9a.patch"
+ "@trezor/connect-web@npm:^9.1.11": "patch:@trezor/connect-web@npm%3A9.3.0#~/.yarn/patches/@trezor-connect-web-npm-9.3.0-040ab10d9a.patch",
+ "path-to-regexp": "1.9.0"
},
"dependencies": {
"@babel/runtime": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch",
diff --git a/yarn.lock b/yarn.lock
index d0660f4d3233..c67922eaa24d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -28708,26 +28708,12 @@ __metadata:
languageName: node
linkType: hard
-"path-to-regexp@npm:0.1.7":
- version: 0.1.7
- resolution: "path-to-regexp@npm:0.1.7"
- checksum: 10/701c99e1f08e3400bea4d701cf6f03517474bb1b608da71c78b1eb261415b645c5670dfae49808c89e12cea2dccd113b069f040a80de012da0400191c6dbd1c8
- languageName: node
- linkType: hard
-
-"path-to-regexp@npm:2.2.1":
- version: 2.2.1
- resolution: "path-to-regexp@npm:2.2.1"
- checksum: 10/1a7125f8c1b5904d556a29722333219df4aa779039e903efe2fbfe0cc3ae9246672846fc8ad285664020b70e434347e0bc9af691fd7d61df8eaa7b018dcd56fb
- languageName: node
- linkType: hard
-
-"path-to-regexp@npm:^1.7.0":
- version: 1.7.0
- resolution: "path-to-regexp@npm:1.7.0"
+"path-to-regexp@npm:1.9.0":
+ version: 1.9.0
+ resolution: "path-to-regexp@npm:1.9.0"
dependencies:
isarray: "npm:0.0.1"
- checksum: 10/7e1275a34fcfed7ba9d0d82ea7149f0c87d8c941c9b34109ab455cceb783b6387ce9275deeb6519eb0f880777a44bcb387cd579d3bb0cfbf4e7fe93c0e3b1a69
+ checksum: 10/67f0f4823f7aab356523d93a83f9f8222bdd119fa0b27a8f8b587e8e6c9825294bb4ccd16ae619def111ff3fe5d15ff8f658cdd3b0d58b9c882de6fd15bc1b76
languageName: node
linkType: hard
From dac872f3b751fbd46a53bd80af6018f26f6893ff Mon Sep 17 00:00:00 2001
From: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com>
Date: Mon, 16 Sep 2024 15:03:26 -0300
Subject: [PATCH 18/43] fix: remove repeated account option (#27116)
---
.../account-list-menu/account-list-menu.tsx | 19 -------------------
1 file changed, 19 deletions(-)
diff --git a/ui/components/multichain/account-list-menu/account-list-menu.tsx b/ui/components/multichain/account-list-menu/account-list-menu.tsx
index 2afbe6f1fcbc..653e6700c0a8 100644
--- a/ui/components/multichain/account-list-menu/account-list-menu.tsx
+++ b/ui/components/multichain/account-list-menu/account-list-menu.tsx
@@ -420,25 +420,6 @@ export const AccountListMenu = ({
) : null
///: END:ONLY_INCLUDE_IF
}
- {
- ///: BEGIN:ONLY_INCLUDE_IF(build-flask)
- bitcoinTestnetSupportEnabled ? (
-
- {
- setActionMode(ACTION_MODES.ADD_BITCOIN_TESTNET);
- }}
- data-testid="multichain-account-menu-popover-add-account-testnet"
- >
- {t('addNewBitcoinTestnetAccount')}
-
-
- ) : null
- ///: END:ONLY_INCLUDE_IF
- }
Date: Mon, 16 Sep 2024 20:48:29 +0200
Subject: [PATCH 19/43] fix (cherry-pick): typo (#27010) (#27029)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
This PR fixes a typo for two properties that were updated in a recent
change to the Segment schema.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27010?quickstart=1)
## **Related issues**
[Fixes:](https://github.com/Consensys/segment-schema/pull/211)
## **Manual testing steps**
N/A
## **Screenshots/Recordings**
N/A
### **Before**
N/A
### **After**
N/A
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] 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**
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27029?quickstart=1)
## **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 Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
.../notifications-settings-per-account.tsx | 2 +-
.../notifications-settings/notifications-settings-types.tsx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/ui/pages/notifications-settings/notifications-settings-per-account.tsx b/ui/pages/notifications-settings/notifications-settings-per-account.tsx
index e73d6807feff..4e5afa6cb5f1 100644
--- a/ui/pages/notifications-settings/notifications-settings-per-account.tsx
+++ b/ui/pages/notifications-settings/notifications-settings-per-account.tsx
@@ -74,7 +74,7 @@ export const NotificationsSettingsPerAccount = ({
category: MetaMetricsEventCategory.NotificationSettings,
event: MetaMetricsEventName.NotificationsSettingsUpdated,
properties: {
- setting_type: 'account_notifications',
+ settings_type: 'account_notifications',
old_value: isEnabled,
new_value: !isEnabled,
},
diff --git a/ui/pages/notifications-settings/notifications-settings-types.tsx b/ui/pages/notifications-settings/notifications-settings-types.tsx
index 5b6b58763214..ba2516644e3b 100644
--- a/ui/pages/notifications-settings/notifications-settings-types.tsx
+++ b/ui/pages/notifications-settings/notifications-settings-types.tsx
@@ -58,7 +58,7 @@ export function NotificationsSettingsTypes({
category: MetaMetricsEventCategory.NotificationSettings,
event: MetaMetricsEventName.NotificationsSettingsUpdated,
properties: {
- setting_type: 'product_announcements',
+ settings_type: 'product_announcements',
old_value: featureAnnouncementsEnabled,
new_value: !featureAnnouncementsEnabled,
},
From bcd40f6a91e3195ed89640cbb0542775f338dbfd Mon Sep 17 00:00:00 2001
From: Matteo Scurati
Date: Mon, 16 Sep 2024 20:49:03 +0200
Subject: [PATCH 20/43] fix: (cherry-pick) check if the notifications started
flow is running (#27038) (#27056)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
This PR adds a check to the modal for enabling notifications. If the
enabling process is in progress, closing the modal does not trigger the
“dismissed” event.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27038?quickstart=1)
## **Related issues**
N/A
## **Manual testing steps**
N/A
## **Screenshots/Recordings**
N/A
### **Before**
N/A
### **After**
N/A
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [x] 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.
---
.../turn-on-metamask-notifications.tsx | 27 +++++++++++--------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/ui/components/app/modals/turn-on-metamask-notifications/turn-on-metamask-notifications.tsx b/ui/components/app/modals/turn-on-metamask-notifications/turn-on-metamask-notifications.tsx
index e63e0a019b2f..de3da35fa841 100644
--- a/ui/components/app/modals/turn-on-metamask-notifications/turn-on-metamask-notifications.tsx
+++ b/ui/components/app/modals/turn-on-metamask-notifications/turn-on-metamask-notifications.tsx
@@ -51,14 +51,14 @@ export default function TurnOnMetamaskNotifications() {
);
const isProfileSyncingEnabled = useSelector(selectIsProfileSyncingEnabled);
- const [buttonState, setButtonState] = useState(
+ const [isLoading, setIsLoading] = useState(
isUpdatingMetamaskNotifications,
);
const { createNotifications, error } = useCreateNotifications();
const handleTurnOnNotifications = async () => {
- setButtonState(true);
+ setIsLoading(true);
await createNotifications();
trackEvent({
category: MetaMetricsEventCategory.NotificationsActivationFlow,
@@ -72,13 +72,18 @@ export default function TurnOnMetamaskNotifications() {
const handleHideModal = () => {
hideModal();
- trackEvent({
- category: MetaMetricsEventCategory.NotificationsActivationFlow,
- event: MetaMetricsEventName.NotificationsActivated,
- properties: {
- is_profile_syncing_enabled: isProfileSyncingEnabled,
- action_type: 'dismissed',
- },
+ setIsLoading((prevLoadingState) => {
+ if (!prevLoadingState) {
+ trackEvent({
+ category: MetaMetricsEventCategory.NotificationsActivationFlow,
+ event: MetaMetricsEventName.NotificationsActivated,
+ properties: {
+ is_profile_syncing_enabled: isProfileSyncingEnabled,
+ action_type: 'dismissed',
+ },
+ });
+ }
+ return prevLoadingState;
});
};
@@ -149,8 +154,8 @@ export default function TurnOnMetamaskNotifications() {
}}
submitButtonProps={{
children: t('turnOnMetamaskNotificationsButton'),
- loading: buttonState,
- disabled: buttonState,
+ loading: isLoading,
+ disabled: isLoading,
'data-testid': 'turn-on-notifications-button',
}}
/>
From 02de2abf2529e27cfcfd62ae7e88a7d1310b0aae Mon Sep 17 00:00:00 2001
From: David Walsh
Date: Mon, 16 Sep 2024 13:53:54 -0500
Subject: [PATCH 21/43] fix (cherry-pick): Don't show AccountListMenu back
button by default (#27152)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
A recent change
(https://github.com/MetaMask/metamask-extension/pull/26271) made it such
that the "<" (back button) in the `AccountListMenu` component always
shows. We do *not* want this when the `AccountListMenu` first opens, so
this PR ensures that.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/26940?quickstart=1)
## **Related issues**
Fixes:
## **Manual testing steps**
1. Open the `AccountListMenu`
2. Don't see the `<`
3. Click the "Add account" button
4. See the `<`
5. Click the `<`, go back to main menu
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
.../component-library/modal-header/modal-header.types.ts | 2 +-
.../multichain/account-list-menu/account-list-menu.test.tsx | 1 +
.../multichain/account-list-menu/account-list-menu.tsx | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/ui/components/component-library/modal-header/modal-header.types.ts b/ui/components/component-library/modal-header/modal-header.types.ts
index e169c8e5709a..8b09318bf622 100644
--- a/ui/components/component-library/modal-header/modal-header.types.ts
+++ b/ui/components/component-library/modal-header/modal-header.types.ts
@@ -17,7 +17,7 @@ export interface ModalHeaderProps extends HeaderBaseStyleUtilityProps {
* The onClick handler for the back `ButtonIcon`
* When passed this will allow for the back `ButtonIcon` to show
*/
- onBack?: () => void;
+ onBack?: () => void | undefined;
/**
* The props to pass to the back `ButtonIcon`
*/
diff --git a/ui/components/multichain/account-list-menu/account-list-menu.test.tsx b/ui/components/multichain/account-list-menu/account-list-menu.test.tsx
index 60e1ca8aa99f..c55116bd2d93 100644
--- a/ui/components/multichain/account-list-menu/account-list-menu.test.tsx
+++ b/ui/components/multichain/account-list-menu/account-list-menu.test.tsx
@@ -117,6 +117,7 @@ describe('AccountListMenu', () => {
expect(getByPlaceholderText('Search accounts')).toBeInTheDocument();
expect(getByText('Add account or hardware wallet')).toBeInTheDocument();
+ expect(document.querySelector('[aria-label="Back"]')).toStrictEqual(null);
});
it('displays accounts for list and filters by search', () => {
diff --git a/ui/components/multichain/account-list-menu/account-list-menu.tsx b/ui/components/multichain/account-list-menu/account-list-menu.tsx
index 653e6700c0a8..f74d1c12a524 100644
--- a/ui/components/multichain/account-list-menu/account-list-menu.tsx
+++ b/ui/components/multichain/account-list-menu/account-list-menu.tsx
@@ -265,7 +265,7 @@ export const AccountListMenu = ({
);
// eslint-disable-next-line no-empty-function
- let onBack = () => {};
+ let onBack;
if (actionMode !== ACTION_MODES.LIST) {
if (actionMode === ACTION_MODES.MENU) {
onBack = () => setActionMode(ACTION_MODES.LIST);
From ad728f79983a014fc37e16734d2e31cffeb1d4fe Mon Sep 17 00:00:00 2001
From: Ariella Vu <20778143+digiwand@users.noreply.github.com>
Date: Tue, 17 Sep 2024 02:55:49 +0800
Subject: [PATCH 22/43] fix: cherry-pick V12.3.0 fix: PermitTransferFrom or
PermitBatchTransferFrom crashes MM when value for Name address has not been
loaded (#27168)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
cherry-picks https://github.com/MetaMask/metamask-extension/pull/26791
into V12.3.0
no conflicts
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27168?quickstart=1)
## **Related issues**
Fixes: https://github.com/MetaMask/metamask-extension/issues/26593
## **Manual testing steps**
1. Go to this page...
2.
3.
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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/name/__snapshots__/name.test.tsx.snap | 18 ++
.../__snapshots__/name-details.test.tsx.snap | 182 ++++++++++++++++++
.../name/name-details/name-details.test.tsx | 13 ++
.../app/name/name-details/name-details.tsx | 4 +
ui/components/app/name/name.test.tsx | 14 ++
ui/components/app/name/name.tsx | 4 +
6 files changed, 235 insertions(+)
diff --git a/ui/components/app/name/__snapshots__/name.test.tsx.snap b/ui/components/app/name/__snapshots__/name.test.tsx.snap
index c3dd86968b31..ee4899a0c866 100644
--- a/ui/components/app/name/__snapshots__/name.test.tsx.snap
+++ b/ui/components/app/name/__snapshots__/name.test.tsx.snap
@@ -79,3 +79,21 @@ exports[`Name renders address with saved name 1`] = `
`;
+
+exports[`Name renders when no address value is passed 1`] = `
+
+`;
diff --git a/ui/components/app/name/name-details/__snapshots__/name-details.test.tsx.snap b/ui/components/app/name/name-details/__snapshots__/name-details.test.tsx.snap
index 6ba786d17e2e..4cc537529b14 100644
--- a/ui/components/app/name/name-details/__snapshots__/name-details.test.tsx.snap
+++ b/ui/components/app/name/name-details/__snapshots__/name-details.test.tsx.snap
@@ -259,6 +259,188 @@ exports[`NameDetails renders proposed names 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+ If you know this address, give it a nickname to recognize it in the future.
+
+
+
+ Address
+
+
+
+
+
+
+
+
+
+ Nickname
+
+
+
+
+
+
+
+
+
+
{
useDispatchMock.mockReturnValue(jest.fn());
});
+ it('renders when no address value is passed', () => {
+ const { baseElement } = renderWithProvider(
+
undefined}
+ />,
+ store,
+ );
+
+ expect(baseElement).toMatchSnapshot();
+ });
+
it('renders with no saved name', () => {
const { baseElement } = renderWithProvider(
& {
};
function formatValue(value: string, type: NameType): string {
+ if (!value.length) {
+ return value;
+ }
+
switch (type) {
case NameType.ETHEREUM_ADDRESS:
return toChecksumAddress(value);
diff --git a/ui/components/app/name/name.test.tsx b/ui/components/app/name/name.test.tsx
index b56c62e5fc2a..a1c8ab8990b7 100644
--- a/ui/components/app/name/name.test.tsx
+++ b/ui/components/app/name/name.test.tsx
@@ -38,6 +38,20 @@ describe('Name', () => {
jest.resetAllMocks();
});
+ it('renders when no address value is passed', () => {
+ useDisplayNameMock.mockReturnValue({
+ name: null,
+ hasPetname: false,
+ });
+
+ const { container } = renderWithProvider(
+ ,
+ store,
+ );
+
+ expect(container).toMatchSnapshot();
+ });
+
it('renders address with no saved name', () => {
useDisplayNameMock.mockReturnValue({
name: null,
diff --git a/ui/components/app/name/name.tsx b/ui/components/app/name/name.tsx
index a5accdc5306e..7311eece2db3 100644
--- a/ui/components/app/name/name.tsx
+++ b/ui/components/app/name/name.tsx
@@ -41,6 +41,10 @@ export type NameProps = {
};
function formatValue(value: string, type: NameType): string {
+ if (!value.length) {
+ return value;
+ }
+
switch (type) {
case NameType.ETHEREUM_ADDRESS:
return shortenAddress(toChecksumAddress(value));
From 5de824bce89ad7126d07c9aab40440947f76d3e4 Mon Sep 17 00:00:00 2001
From: MetaMask Bot
Date: Tue, 17 Sep 2024 09:57:17 +0000
Subject: [PATCH 23/43] Version v12.2.4
---
CHANGELOG.md | 5 ++++-
package.json | 2 +-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ad00f06ec372..bc3b1ad214ec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [12.2.4]
+
## [12.2.3]
### Fixed
- Fixes dapps integrating with the cosmos chain that rely on setting the `verifyingContract` field of a signature to `"cosmos"`
@@ -5048,7 +5050,8 @@ Update styles and spacing on the critical error page ([#20350](https://github.c
- Added the ability to restore accounts from seed words.
-[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v12.2.3...HEAD
+[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v12.2.4...HEAD
+[12.2.4]: https://github.com/MetaMask/metamask-extension/compare/v12.2.3...v12.2.4
[12.2.3]: https://github.com/MetaMask/metamask-extension/compare/v12.2.2...v12.2.3
[12.2.2]: https://github.com/MetaMask/metamask-extension/compare/v12.2.1...v12.2.2
[12.2.1]: https://github.com/MetaMask/metamask-extension/compare/v12.2.0...v12.2.1
diff --git a/package.json b/package.json
index 541a6a7bba82..e796cab76162 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "metamask-crx",
- "version": "12.2.3",
+ "version": "12.2.4",
"private": true,
"repository": {
"type": "git",
From 4b48aa972980e61cd8fb8fb09762039337dd1f3d Mon Sep 17 00:00:00 2001
From: Dan J Miller
Date: Tue, 17 Sep 2024 07:39:45 -0230
Subject: [PATCH 24/43] Update changelog for v12.2.4 (#27207)
V12.2.4 changelog
---
CHANGELOG.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bc3b1ad214ec..529d6764a977 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [12.2.4]
+### Fixed
+- Fixes token approvals for users who have the "Decode smart contracts" setting toggled off ([#27203](https://github.com/MetaMask/metamask-extension/pull/27203))
## [12.2.3]
### Fixed
From 04d6bd215d9ccd35d19eaa598de8cca4774e38c9 Mon Sep 17 00:00:00 2001
From: Matthew Walsh
Date: Tue, 17 Sep 2024 13:43:22 +0100
Subject: [PATCH 25/43] fix (cherry-pick): incomplete transactions on startup
(#26972)
---
...ion-controller-npm-34.0.0-8bdfa87aaf.patch | 6174 +++++++++++++++++
app/scripts/background.js | 2 -
app/scripts/lib/transaction/mmi-hooks.test.ts | 19 -
app/scripts/lib/transaction/mmi-hooks.ts | 12 -
app/scripts/metamask-controller.js | 2 -
package.json | 4 +-
test/e2e/fixture-builder.js | 599 +-
test/e2e/helpers.js | 40 +-
.../contract-interaction-redesign.spec.ts | 59 +-
.../confirmations/transactions/shared.ts | 2 -
.../tests/transaction/edit-gas-fee.spec.js | 29 +-
.../transaction/navigate-transactions.spec.js | 236 +-
test/e2e/tests/transaction/send-edit.spec.js | 43 +-
yarn.lock | 41 +-
14 files changed, 6437 insertions(+), 825 deletions(-)
create mode 100644 .yarn/patches/@metamask-transaction-controller-npm-34.0.0-8bdfa87aaf.patch
diff --git a/.yarn/patches/@metamask-transaction-controller-npm-34.0.0-8bdfa87aaf.patch b/.yarn/patches/@metamask-transaction-controller-npm-34.0.0-8bdfa87aaf.patch
new file mode 100644
index 000000000000..4ba6272f67bf
--- /dev/null
+++ b/.yarn/patches/@metamask-transaction-controller-npm-34.0.0-8bdfa87aaf.patch
@@ -0,0 +1,6174 @@
+diff --git a/dist/TransactionController.js b/dist/TransactionController.js
+index bdb836a895f9bfdc9225c354b59c0aaab20f80c1..f03dc65ff723256e1d4ed2588199166f0ee6e3cc 100644
+--- a/dist/TransactionController.js
++++ b/dist/TransactionController.js
+@@ -4,13 +4,13 @@
+
+
+
+-var _chunkS7Q622ISjs = require('./chunk-S7Q622IS.js');
++var _chunkIVR4NMOFjs = require('./chunk-IVR4NMOF.js');
+ require('./chunk-PRUNMTRD.js');
+ require('./chunk-74W7X6BE.js');
+ require('./chunk-KT6UAKBB.js');
+ require('./chunk-SD6CWFDF.js');
+ require('./chunk-RXIUMVA5.js');
+-require('./chunk-ULD4JC3Q.js');
++require('./chunk-6DODV6OV.js');
+ require('./chunk-7LXE4KHV.js');
+ require('./chunk-V72C4MCR.js');
+ require('./chunk-QP75SWIQ.js');
+@@ -41,5 +41,5 @@ require('./chunk-Z4BLTVTB.js');
+
+
+
+-exports.ApprovalState = _chunkS7Q622ISjs.ApprovalState; exports.CANCEL_RATE = _chunkS7Q622ISjs.CANCEL_RATE; exports.HARDFORK = _chunkS7Q622ISjs.HARDFORK; exports.SPEED_UP_RATE = _chunkS7Q622ISjs.SPEED_UP_RATE; exports.TransactionController = _chunkS7Q622ISjs.TransactionController;
++exports.ApprovalState = _chunkIVR4NMOFjs.ApprovalState; exports.CANCEL_RATE = _chunkIVR4NMOFjs.CANCEL_RATE; exports.HARDFORK = _chunkIVR4NMOFjs.HARDFORK; exports.SPEED_UP_RATE = _chunkIVR4NMOFjs.SPEED_UP_RATE; exports.TransactionController = _chunkIVR4NMOFjs.TransactionController;
+ //# sourceMappingURL=TransactionController.js.map
+\ No newline at end of file
+diff --git a/dist/TransactionController.mjs b/dist/TransactionController.mjs
+index ac7d4c27a4bca05f03cb791441e9e5d87765bbf2..88ecaa74d9e133c02fe09341460f4dca2dd83865 100644
+--- a/dist/TransactionController.mjs
++++ b/dist/TransactionController.mjs
+@@ -4,13 +4,13 @@ import {
+ HARDFORK,
+ SPEED_UP_RATE,
+ TransactionController
+-} from "./chunk-UKV5HIMT.mjs";
++} from "./chunk-YQYO6EGF.mjs";
+ import "./chunk-6DDVVUJC.mjs";
+ import "./chunk-EVL6KODQ.mjs";
+ import "./chunk-K4KOSAGM.mjs";
+ import "./chunk-KG4UW4K4.mjs";
+ import "./chunk-5ZEJT5SN.mjs";
+-import "./chunk-6B5BEO3R.mjs";
++import "./chunk-7M2R5AHC.mjs";
+ import "./chunk-FRKQ3Z2L.mjs";
+ import "./chunk-5G6OHAXI.mjs";
+ import "./chunk-XGRAHX6T.mjs";
+diff --git a/dist/chunk-6DODV6OV.js b/dist/chunk-6DODV6OV.js
+new file mode 100644
+index 0000000000000000000000000000000000000000..92a813c417d809304e216783e76b6a67651d4661
+--- /dev/null
++++ b/dist/chunk-6DODV6OV.js
+@@ -0,0 +1,390 @@
++"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
++
++
++var _chunkS6VGOPUYjs = require('./chunk-S6VGOPUY.js');
++
++
++
++
++
++var _chunkZ4BLTVTBjs = require('./chunk-Z4BLTVTB.js');
++
++// src/helpers/PendingTransactionTracker.ts
++var _controllerutils = require('@metamask/controller-utils');
++var _events = require('events'); var _events2 = _interopRequireDefault(_events);
++var _lodash = require('lodash');
++var DROPPED_BLOCK_COUNT = 3;
++var RECEIPT_STATUS_SUCCESS = "0x1";
++var RECEIPT_STATUS_FAILURE = "0x0";
++var MAX_RETRY_BLOCK_DISTANCE = 50;
++var KNOWN_TRANSACTION_ERRORS = [
++ "replacement transaction underpriced",
++ "known transaction",
++ "gas price too low to replace",
++ "transaction with the same hash was already imported",
++ "gateway timeout",
++ "nonce too low"
++];
++var log = _chunkS6VGOPUYjs.createModuleLogger.call(void 0, _chunkS6VGOPUYjs.projectLogger, "pending-transactions");
++var _blockTracker, _droppedBlockCountByHash, _getChainId, _getEthQuery, _getTransactions, _isResubmitEnabled, _listener, _getGlobalLock, _publishTransaction, _running, _beforeCheckPendingTransaction, _beforePublish, _start, start_fn, _onLatestBlock, onLatestBlock_fn, _checkTransactions, checkTransactions_fn, _resubmitTransactions, resubmitTransactions_fn, _isKnownTransactionError, isKnownTransactionError_fn, _resubmitTransaction, resubmitTransaction_fn, _isResubmitDue, isResubmitDue_fn, _checkTransaction, checkTransaction_fn, _onTransactionConfirmed, onTransactionConfirmed_fn, _isTransactionDropped, isTransactionDropped_fn, _isNonceTaken, isNonceTaken_fn, _getPendingTransactions, getPendingTransactions_fn, _warnTransaction, warnTransaction_fn, _failTransaction, failTransaction_fn, _dropTransaction, dropTransaction_fn, _updateTransaction, updateTransaction_fn, _getTransactionReceipt, getTransactionReceipt_fn, _getBlockByHash, getBlockByHash_fn, _getNetworkTransactionCount, getNetworkTransactionCount_fn, _getCurrentChainTransactions, getCurrentChainTransactions_fn;
++var PendingTransactionTracker = class {
++ constructor({
++ blockTracker,
++ getChainId,
++ getEthQuery,
++ getTransactions,
++ isResubmitEnabled,
++ getGlobalLock,
++ publishTransaction,
++ hooks
++ }) {
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _start);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _onLatestBlock);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _checkTransactions);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _resubmitTransactions);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _isKnownTransactionError);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _resubmitTransaction);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _isResubmitDue);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _checkTransaction);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _onTransactionConfirmed);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _isTransactionDropped);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _isNonceTaken);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getPendingTransactions);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _warnTransaction);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _failTransaction);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _dropTransaction);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _updateTransaction);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getTransactionReceipt);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getBlockByHash);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getNetworkTransactionCount);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getCurrentChainTransactions);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _blockTracker, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _droppedBlockCountByHash, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getChainId, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getEthQuery, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getTransactions, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _isResubmitEnabled, void 0);
++ // TODO: Replace `any` with type
++ // eslint-disable-next-line @typescript-eslint/no-explicit-any
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _listener, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getGlobalLock, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _publishTransaction, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _running, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _beforeCheckPendingTransaction, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _beforePublish, void 0);
++ this.startIfPendingTransactions = () => {
++ const pendingTransactions = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getPendingTransactions, getPendingTransactions_fn).call(this);
++ if (pendingTransactions.length) {
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _start, start_fn).call(this);
++ } else {
++ this.stop();
++ }
++ };
++ this.hub = new (0, _events2.default)();
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _blockTracker, blockTracker);
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _droppedBlockCountByHash, /* @__PURE__ */ new Map());
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _getChainId, getChainId);
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _getEthQuery, getEthQuery);
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _getTransactions, getTransactions);
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _isResubmitEnabled, isResubmitEnabled ?? (() => true));
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _listener, _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _onLatestBlock, onLatestBlock_fn).bind(this));
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _getGlobalLock, getGlobalLock);
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _publishTransaction, publishTransaction);
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _running, false);
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _beforePublish, hooks?.beforePublish ?? (() => true));
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _beforeCheckPendingTransaction, hooks?.beforeCheckPendingTransaction ?? (() => true));
++ }
++ /**
++ * Force checks the network if the given transaction is confirmed and updates it's status.
++ *
++ * @param txMeta - The transaction to check
++ */
++ async forceCheckTransaction(txMeta) {
++ const releaseLock = await _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getGlobalLock).call(this);
++ try {
++ await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _checkTransaction, checkTransaction_fn).call(this, txMeta);
++ } catch (error) {
++ log("Failed to check transaction", error);
++ } finally {
++ releaseLock();
++ }
++ }
++ stop() {
++ if (!_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _running)) {
++ return;
++ }
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _blockTracker).removeListener("latest", _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _listener));
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _running, false);
++ log("Stopped polling");
++ }
++};
++_blockTracker = new WeakMap();
++_droppedBlockCountByHash = new WeakMap();
++_getChainId = new WeakMap();
++_getEthQuery = new WeakMap();
++_getTransactions = new WeakMap();
++_isResubmitEnabled = new WeakMap();
++_listener = new WeakMap();
++_getGlobalLock = new WeakMap();
++_publishTransaction = new WeakMap();
++_running = new WeakMap();
++_beforeCheckPendingTransaction = new WeakMap();
++_beforePublish = new WeakMap();
++_start = new WeakSet();
++start_fn = function() {
++ if (_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _running)) {
++ return;
++ }
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _blockTracker).on("latest", _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _listener));
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _running, true);
++ log("Started polling");
++};
++_onLatestBlock = new WeakSet();
++onLatestBlock_fn = async function(latestBlockNumber) {
++ const releaseLock = await _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getGlobalLock).call(this);
++ try {
++ await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _checkTransactions, checkTransactions_fn).call(this);
++ } catch (error) {
++ log("Failed to check transactions", error);
++ } finally {
++ releaseLock();
++ }
++ try {
++ await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _resubmitTransactions, resubmitTransactions_fn).call(this, latestBlockNumber);
++ } catch (error) {
++ log("Failed to resubmit transactions", error);
++ }
++};
++_checkTransactions = new WeakSet();
++checkTransactions_fn = async function() {
++ log("Checking transactions");
++ const pendingTransactions = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getPendingTransactions, getPendingTransactions_fn).call(this);
++ if (!pendingTransactions.length) {
++ log("No pending transactions to check");
++ return;
++ }
++ log("Found pending transactions to check", {
++ count: pendingTransactions.length,
++ ids: pendingTransactions.map((tx) => tx.id)
++ });
++ await Promise.all(
++ pendingTransactions.map((tx) => _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _checkTransaction, checkTransaction_fn).call(this, tx))
++ );
++};
++_resubmitTransactions = new WeakSet();
++resubmitTransactions_fn = async function(latestBlockNumber) {
++ if (!_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _isResubmitEnabled).call(this) || !_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _running)) {
++ return;
++ }
++ log("Resubmitting transactions");
++ const pendingTransactions = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getPendingTransactions, getPendingTransactions_fn).call(this);
++ if (!pendingTransactions.length) {
++ log("No pending transactions to resubmit");
++ return;
++ }
++ log("Found pending transactions to resubmit", {
++ count: pendingTransactions.length,
++ ids: pendingTransactions.map((tx) => tx.id)
++ });
++ for (const txMeta of pendingTransactions) {
++ try {
++ await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _resubmitTransaction, resubmitTransaction_fn).call(this, txMeta, latestBlockNumber);
++ } catch (error) {
++ const errorMessage = error.value?.message?.toLowerCase() || error.message?.toLowerCase() || String(error);
++ if (_chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _isKnownTransactionError, isKnownTransactionError_fn).call(this, errorMessage)) {
++ log("Ignoring known transaction error", errorMessage);
++ continue;
++ }
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _warnTransaction, warnTransaction_fn).call(this, txMeta, error.message, "There was an error when resubmitting this transaction.");
++ }
++ }
++};
++_isKnownTransactionError = new WeakSet();
++isKnownTransactionError_fn = function(errorMessage) {
++ return KNOWN_TRANSACTION_ERRORS.some(
++ (knownError) => errorMessage.includes(knownError)
++ );
++};
++_resubmitTransaction = new WeakSet();
++resubmitTransaction_fn = async function(txMeta, latestBlockNumber) {
++ if (!_chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _isResubmitDue, isResubmitDue_fn).call(this, txMeta, latestBlockNumber)) {
++ return;
++ }
++ const { rawTx } = txMeta;
++ if (!_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _beforePublish).call(this, txMeta)) {
++ return;
++ }
++ const ethQuery = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getEthQuery).call(this, txMeta.networkClientId);
++ await _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _publishTransaction).call(this, ethQuery, rawTx);
++ const retryCount = (txMeta.retryCount ?? 0) + 1;
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateTransaction, updateTransaction_fn).call(this, _lodash.merge.call(void 0, {}, txMeta, { retryCount }), "PendingTransactionTracker:transaction-retry - Retry count increased");
++};
++_isResubmitDue = new WeakSet();
++isResubmitDue_fn = function(txMeta, latestBlockNumber) {
++ const txMetaWithFirstRetryBlockNumber = _lodash.cloneDeep.call(void 0, txMeta);
++ if (!txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber) {
++ txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber = latestBlockNumber;
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateTransaction, updateTransaction_fn).call(this, txMetaWithFirstRetryBlockNumber, "PendingTransactionTracker:#isResubmitDue - First retry block number set");
++ }
++ const { firstRetryBlockNumber } = txMetaWithFirstRetryBlockNumber;
++ const blocksSinceFirstRetry = Number.parseInt(latestBlockNumber, 16) - Number.parseInt(firstRetryBlockNumber, 16);
++ const retryCount = txMeta.retryCount || 0;
++ const requiredBlocksSinceFirstRetry = Math.min(
++ MAX_RETRY_BLOCK_DISTANCE,
++ Math.pow(2, retryCount)
++ );
++ return blocksSinceFirstRetry >= requiredBlocksSinceFirstRetry;
++};
++_checkTransaction = new WeakSet();
++checkTransaction_fn = async function(txMeta) {
++ const { hash, id } = txMeta;
++ if (!hash && _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _beforeCheckPendingTransaction).call(this, txMeta)) {
++ const error = new Error(
++ "We had an error while submitting this transaction, please try again."
++ );
++ error.name = "NoTxHashError";
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _failTransaction, failTransaction_fn).call(this, txMeta, error);
++ return;
++ }
++ if (_chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _isNonceTaken, isNonceTaken_fn).call(this, txMeta)) {
++ log("Nonce already taken", id);
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _dropTransaction, dropTransaction_fn).call(this, txMeta);
++ return;
++ }
++ try {
++ const receipt = await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getTransactionReceipt, getTransactionReceipt_fn).call(this, hash);
++ const isSuccess = receipt?.status === RECEIPT_STATUS_SUCCESS;
++ const isFailure = receipt?.status === RECEIPT_STATUS_FAILURE;
++ if (isFailure) {
++ log("Transaction receipt has failed status");
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _failTransaction, failTransaction_fn).call(this, txMeta, new Error("Transaction dropped or replaced"));
++ return;
++ }
++ const { blockNumber, blockHash } = receipt || {};
++ if (isSuccess && blockNumber && blockHash) {
++ await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _onTransactionConfirmed, onTransactionConfirmed_fn).call(this, txMeta, {
++ ...receipt,
++ blockNumber,
++ blockHash
++ });
++ return;
++ }
++ } catch (error) {
++ log("Failed to check transaction", id, error);
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _warnTransaction, warnTransaction_fn).call(this, txMeta, error.message, "There was a problem loading this transaction.");
++ return;
++ }
++ if (await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _isTransactionDropped, isTransactionDropped_fn).call(this, txMeta)) {
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _dropTransaction, dropTransaction_fn).call(this, txMeta);
++ }
++};
++_onTransactionConfirmed = new WeakSet();
++onTransactionConfirmed_fn = async function(txMeta, receipt) {
++ const { id } = txMeta;
++ const { blockHash } = receipt;
++ log("Transaction confirmed", id);
++ const { baseFeePerGas, timestamp: blockTimestamp } = await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getBlockByHash, getBlockByHash_fn).call(this, blockHash, false);
++ const updatedTxMeta = _lodash.cloneDeep.call(void 0, txMeta);
++ updatedTxMeta.baseFeePerGas = baseFeePerGas;
++ updatedTxMeta.blockTimestamp = blockTimestamp;
++ updatedTxMeta.status = "confirmed" /* confirmed */;
++ updatedTxMeta.txParams = {
++ ...updatedTxMeta.txParams,
++ gasUsed: receipt.gasUsed
++ };
++ updatedTxMeta.txReceipt = receipt;
++ updatedTxMeta.verifiedOnBlockchain = true;
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateTransaction, updateTransaction_fn).call(this, updatedTxMeta, "PendingTransactionTracker:#onTransactionConfirmed - Transaction confirmed");
++ this.hub.emit("transaction-confirmed", updatedTxMeta);
++};
++_isTransactionDropped = new WeakSet();
++isTransactionDropped_fn = async function(txMeta) {
++ const {
++ hash,
++ id,
++ txParams: { nonce, from }
++ } = txMeta;
++ if (!nonce || !hash) {
++ return false;
++ }
++ const networkNextNonceHex = await _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getNetworkTransactionCount, getNetworkTransactionCount_fn).call(this, from);
++ const networkNextNonceNumber = parseInt(networkNextNonceHex, 16);
++ const nonceNumber = parseInt(nonce, 16);
++ if (nonceNumber >= networkNextNonceNumber) {
++ return false;
++ }
++ let droppedBlockCount = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _droppedBlockCountByHash).get(hash);
++ if (droppedBlockCount === void 0) {
++ droppedBlockCount = 0;
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _droppedBlockCountByHash).set(hash, droppedBlockCount);
++ }
++ if (droppedBlockCount < DROPPED_BLOCK_COUNT) {
++ log("Incrementing dropped block count", { id, droppedBlockCount });
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _droppedBlockCountByHash).set(hash, droppedBlockCount + 1);
++ return false;
++ }
++ log("Hit dropped block count", id);
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _droppedBlockCountByHash).delete(hash);
++ return true;
++};
++_isNonceTaken = new WeakSet();
++isNonceTaken_fn = function(txMeta) {
++ const { id, txParams } = txMeta;
++ return _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getCurrentChainTransactions, getCurrentChainTransactions_fn).call(this).some(
++ (tx) => tx.id !== id && tx.txParams.from === txParams.from && tx.status === "confirmed" /* confirmed */ && tx.txParams.nonce === txParams.nonce && tx.type !== "incoming" /* incoming */
++ );
++};
++_getPendingTransactions = new WeakSet();
++getPendingTransactions_fn = function() {
++ return _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getCurrentChainTransactions, getCurrentChainTransactions_fn).call(this).filter(
++ (tx) => tx.status === "submitted" /* submitted */ && !tx.verifiedOnBlockchain && !tx.isUserOperation
++ );
++};
++_warnTransaction = new WeakSet();
++warnTransaction_fn = function(txMeta, error, message) {
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateTransaction, updateTransaction_fn).call(this, {
++ ...txMeta,
++ warning: { error, message }
++ }, "PendingTransactionTracker:#warnTransaction - Warning added");
++};
++_failTransaction = new WeakSet();
++failTransaction_fn = function(txMeta, error) {
++ log("Transaction failed", txMeta.id, error);
++ this.hub.emit("transaction-failed", txMeta, error);
++};
++_dropTransaction = new WeakSet();
++dropTransaction_fn = function(txMeta) {
++ log("Transaction dropped", txMeta.id);
++ this.hub.emit("transaction-dropped", txMeta);
++};
++_updateTransaction = new WeakSet();
++updateTransaction_fn = function(txMeta, note) {
++ this.hub.emit("transaction-updated", txMeta, note);
++};
++_getTransactionReceipt = new WeakSet();
++getTransactionReceipt_fn = async function(txHash) {
++ return await _controllerutils.query.call(void 0, _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getEthQuery).call(this), "getTransactionReceipt", [txHash]);
++};
++_getBlockByHash = new WeakSet();
++getBlockByHash_fn = async function(blockHash, includeTransactionDetails) {
++ return await _controllerutils.query.call(void 0, _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getEthQuery).call(this), "getBlockByHash", [
++ blockHash,
++ includeTransactionDetails
++ ]);
++};
++_getNetworkTransactionCount = new WeakSet();
++getNetworkTransactionCount_fn = async function(address) {
++ return await _controllerutils.query.call(void 0, _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getEthQuery).call(this), "getTransactionCount", [address]);
++};
++_getCurrentChainTransactions = new WeakSet();
++getCurrentChainTransactions_fn = function() {
++ const currentChainId = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getChainId).call(this);
++ return _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _getTransactions).call(this).filter(
++ (tx) => tx.chainId === currentChainId
++ );
++};
++
++
++
++exports.PendingTransactionTracker = PendingTransactionTracker;
++//# sourceMappingURL=chunk-6DODV6OV.js.map
+\ No newline at end of file
+diff --git a/dist/chunk-6DODV6OV.js.map b/dist/chunk-6DODV6OV.js.map
+new file mode 100644
+index 0000000000000000000000000000000000000000..c982d3394489271e672f68247654349d554c702a
+--- /dev/null
++++ b/dist/chunk-6DODV6OV.js.map
+@@ -0,0 +1 @@
++{"version":3,"sources":["../src/helpers/PendingTransactionTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { query } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport type {\n BlockTracker,\n NetworkClientId,\n} from '@metamask/network-controller';\nimport EventEmitter from 'events';\nimport { cloneDeep, merge } from 'lodash';\n\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { TransactionMeta, TransactionReceipt } from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\n\n/**\n * We wait this many blocks before emitting a 'transaction-dropped' event\n * This is because we could be talking to a node that is out of sync\n */\nconst DROPPED_BLOCK_COUNT = 3;\n\nconst RECEIPT_STATUS_SUCCESS = '0x1';\nconst RECEIPT_STATUS_FAILURE = '0x0';\nconst MAX_RETRY_BLOCK_DISTANCE = 50;\n\nconst KNOWN_TRANSACTION_ERRORS = [\n 'replacement transaction underpriced',\n 'known transaction',\n 'gas price too low to replace',\n 'transaction with the same hash was already imported',\n 'gateway timeout',\n 'nonce too low',\n];\n\nconst log = createModuleLogger(projectLogger, 'pending-transactions');\n\ntype SuccessfulTransactionReceipt = TransactionReceipt & {\n blockNumber: string;\n blockHash: string;\n};\n\ntype Events = {\n 'transaction-confirmed': [txMeta: TransactionMeta];\n 'transaction-dropped': [txMeta: TransactionMeta];\n 'transaction-failed': [txMeta: TransactionMeta, error: Error];\n 'transaction-updated': [txMeta: TransactionMeta, note: string];\n};\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface PendingTransactionTrackerEventEmitter extends EventEmitter {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n on(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): this;\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n emit(eventName: T, ...args: Events[T]): boolean;\n}\n\nexport class PendingTransactionTracker {\n hub: PendingTransactionTrackerEventEmitter;\n\n #blockTracker: BlockTracker;\n\n #droppedBlockCountByHash: Map;\n\n #getChainId: () => string;\n\n #getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n\n #getTransactions: () => TransactionMeta[];\n\n #isResubmitEnabled: () => boolean;\n\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #listener: any;\n\n #getGlobalLock: () => Promise<() => void>;\n\n #publishTransaction: (ethQuery: EthQuery, rawTx: string) => Promise;\n\n #running: boolean;\n\n #beforeCheckPendingTransaction: (transactionMeta: TransactionMeta) => boolean;\n\n #beforePublish: (transactionMeta: TransactionMeta) => boolean;\n\n constructor({\n blockTracker,\n getChainId,\n getEthQuery,\n getTransactions,\n isResubmitEnabled,\n getGlobalLock,\n publishTransaction,\n hooks,\n }: {\n blockTracker: BlockTracker;\n getChainId: () => string;\n getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n getTransactions: () => TransactionMeta[];\n isResubmitEnabled?: () => boolean;\n getGlobalLock: () => Promise<() => void>;\n publishTransaction: (ethQuery: EthQuery, rawTx: string) => Promise;\n hooks?: {\n beforeCheckPendingTransaction?: (\n transactionMeta: TransactionMeta,\n ) => boolean;\n beforePublish?: (transactionMeta: TransactionMeta) => boolean;\n };\n }) {\n this.hub = new EventEmitter() as PendingTransactionTrackerEventEmitter;\n\n this.#blockTracker = blockTracker;\n this.#droppedBlockCountByHash = new Map();\n this.#getChainId = getChainId;\n this.#getEthQuery = getEthQuery;\n this.#getTransactions = getTransactions;\n this.#isResubmitEnabled = isResubmitEnabled ?? (() => true);\n this.#listener = this.#onLatestBlock.bind(this);\n this.#getGlobalLock = getGlobalLock;\n this.#publishTransaction = publishTransaction;\n this.#running = false;\n this.#beforePublish = hooks?.beforePublish ?? (() => true);\n this.#beforeCheckPendingTransaction =\n hooks?.beforeCheckPendingTransaction ?? (() => true);\n }\n\n startIfPendingTransactions = () => {\n const pendingTransactions = this.#getPendingTransactions();\n\n if (pendingTransactions.length) {\n this.#start();\n } else {\n this.stop();\n }\n };\n\n /**\n * Force checks the network if the given transaction is confirmed and updates it's status.\n *\n * @param txMeta - The transaction to check\n */\n async forceCheckTransaction(txMeta: TransactionMeta) {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransaction(txMeta);\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to check transaction', error);\n } finally {\n releaseLock();\n }\n }\n\n #start() {\n if (this.#running) {\n return;\n }\n\n this.#blockTracker.on('latest', this.#listener);\n this.#running = true;\n\n log('Started polling');\n }\n\n stop() {\n if (!this.#running) {\n return;\n }\n\n this.#blockTracker.removeListener('latest', this.#listener);\n this.#running = false;\n\n log('Stopped polling');\n }\n\n async #onLatestBlock(latestBlockNumber: string) {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransactions();\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to check transactions', error);\n } finally {\n releaseLock();\n }\n\n try {\n await this.#resubmitTransactions(latestBlockNumber);\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to resubmit transactions', error);\n }\n }\n\n async #checkTransactions() {\n log('Checking transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n log('No pending transactions to check');\n return;\n }\n\n log('Found pending transactions to check', {\n count: pendingTransactions.length,\n ids: pendingTransactions.map((tx) => tx.id),\n });\n\n await Promise.all(\n pendingTransactions.map((tx) => this.#checkTransaction(tx)),\n );\n }\n\n async #resubmitTransactions(latestBlockNumber: string) {\n if (!this.#isResubmitEnabled() || !this.#running) {\n return;\n }\n\n log('Resubmitting transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n log('No pending transactions to resubmit');\n return;\n }\n\n log('Found pending transactions to resubmit', {\n count: pendingTransactions.length,\n ids: pendingTransactions.map((tx) => tx.id),\n });\n\n for (const txMeta of pendingTransactions) {\n try {\n await this.#resubmitTransaction(txMeta, latestBlockNumber);\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n /* istanbul ignore next */\n const errorMessage =\n error.value?.message?.toLowerCase() ||\n error.message?.toLowerCase() ||\n String(error);\n\n if (this.#isKnownTransactionError(errorMessage)) {\n log('Ignoring known transaction error', errorMessage);\n continue;\n }\n\n this.#warnTransaction(\n txMeta,\n error.message,\n 'There was an error when resubmitting this transaction.',\n );\n }\n }\n }\n\n #isKnownTransactionError(errorMessage: string) {\n return KNOWN_TRANSACTION_ERRORS.some((knownError) =>\n errorMessage.includes(knownError),\n );\n }\n\n async #resubmitTransaction(\n txMeta: TransactionMeta,\n latestBlockNumber: string,\n ) {\n if (!this.#isResubmitDue(txMeta, latestBlockNumber)) {\n return;\n }\n\n const { rawTx } = txMeta;\n\n if (!this.#beforePublish(txMeta)) {\n return;\n }\n\n const ethQuery = this.#getEthQuery(txMeta.networkClientId);\n await this.#publishTransaction(ethQuery, rawTx as string);\n\n const retryCount = (txMeta.retryCount ?? 0) + 1;\n\n this.#updateTransaction(\n merge({}, txMeta, { retryCount }),\n 'PendingTransactionTracker:transaction-retry - Retry count increased',\n );\n }\n\n #isResubmitDue(txMeta: TransactionMeta, latestBlockNumber: string): boolean {\n const txMetaWithFirstRetryBlockNumber = cloneDeep(txMeta);\n\n if (!txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber) {\n txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber = latestBlockNumber;\n\n this.#updateTransaction(\n txMetaWithFirstRetryBlockNumber,\n 'PendingTransactionTracker:#isResubmitDue - First retry block number set',\n );\n }\n\n const { firstRetryBlockNumber } = txMetaWithFirstRetryBlockNumber;\n\n const blocksSinceFirstRetry =\n Number.parseInt(latestBlockNumber, 16) -\n Number.parseInt(firstRetryBlockNumber, 16);\n\n const retryCount = txMeta.retryCount || 0;\n\n // Exponential backoff to limit retries at publishing\n // Capped at ~15 minutes between retries\n const requiredBlocksSinceFirstRetry = Math.min(\n MAX_RETRY_BLOCK_DISTANCE,\n Math.pow(2, retryCount),\n );\n\n return blocksSinceFirstRetry >= requiredBlocksSinceFirstRetry;\n }\n\n async #checkTransaction(txMeta: TransactionMeta) {\n const { hash, id } = txMeta;\n\n if (!hash && this.#beforeCheckPendingTransaction(txMeta)) {\n const error = new Error(\n 'We had an error while submitting this transaction, please try again.',\n );\n\n error.name = 'NoTxHashError';\n\n this.#failTransaction(txMeta, error);\n\n return;\n }\n\n if (this.#isNonceTaken(txMeta)) {\n log('Nonce already taken', id);\n this.#dropTransaction(txMeta);\n return;\n }\n\n try {\n const receipt = await this.#getTransactionReceipt(hash);\n const isSuccess = receipt?.status === RECEIPT_STATUS_SUCCESS;\n const isFailure = receipt?.status === RECEIPT_STATUS_FAILURE;\n\n if (isFailure) {\n log('Transaction receipt has failed status');\n\n this.#failTransaction(\n txMeta,\n new Error('Transaction dropped or replaced'),\n );\n\n return;\n }\n\n const { blockNumber, blockHash } = receipt || {};\n\n if (isSuccess && blockNumber && blockHash) {\n await this.#onTransactionConfirmed(txMeta, {\n ...receipt,\n blockNumber,\n blockHash,\n });\n\n return;\n }\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n log('Failed to check transaction', id, error);\n\n this.#warnTransaction(\n txMeta,\n error.message,\n 'There was a problem loading this transaction.',\n );\n\n return;\n }\n\n if (await this.#isTransactionDropped(txMeta)) {\n this.#dropTransaction(txMeta);\n }\n }\n\n async #onTransactionConfirmed(\n txMeta: TransactionMeta,\n receipt: SuccessfulTransactionReceipt,\n ) {\n const { id } = txMeta;\n const { blockHash } = receipt;\n\n log('Transaction confirmed', id);\n\n const { baseFeePerGas, timestamp: blockTimestamp } =\n await this.#getBlockByHash(blockHash, false);\n\n const updatedTxMeta = cloneDeep(txMeta);\n updatedTxMeta.baseFeePerGas = baseFeePerGas;\n updatedTxMeta.blockTimestamp = blockTimestamp;\n updatedTxMeta.status = TransactionStatus.confirmed;\n updatedTxMeta.txParams = {\n ...updatedTxMeta.txParams,\n gasUsed: receipt.gasUsed,\n };\n updatedTxMeta.txReceipt = receipt;\n updatedTxMeta.verifiedOnBlockchain = true;\n\n this.#updateTransaction(\n updatedTxMeta,\n 'PendingTransactionTracker:#onTransactionConfirmed - Transaction confirmed',\n );\n\n this.hub.emit('transaction-confirmed', updatedTxMeta);\n }\n\n async #isTransactionDropped(txMeta: TransactionMeta) {\n const {\n hash,\n id,\n txParams: { nonce, from },\n } = txMeta;\n\n /* istanbul ignore next */\n if (!nonce || !hash) {\n return false;\n }\n\n const networkNextNonceHex = await this.#getNetworkTransactionCount(from);\n const networkNextNonceNumber = parseInt(networkNextNonceHex, 16);\n const nonceNumber = parseInt(nonce, 16);\n\n if (nonceNumber >= networkNextNonceNumber) {\n return false;\n }\n\n let droppedBlockCount = this.#droppedBlockCountByHash.get(hash);\n\n if (droppedBlockCount === undefined) {\n droppedBlockCount = 0;\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount);\n }\n\n if (droppedBlockCount < DROPPED_BLOCK_COUNT) {\n log('Incrementing dropped block count', { id, droppedBlockCount });\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount + 1);\n return false;\n }\n\n log('Hit dropped block count', id);\n\n this.#droppedBlockCountByHash.delete(hash);\n return true;\n }\n\n #isNonceTaken(txMeta: TransactionMeta): boolean {\n const { id, txParams } = txMeta;\n\n return this.#getCurrentChainTransactions().some(\n (tx) =>\n tx.id !== id &&\n tx.txParams.from === txParams.from &&\n tx.status === TransactionStatus.confirmed &&\n tx.txParams.nonce === txParams.nonce &&\n tx.type !== TransactionType.incoming,\n );\n }\n\n #getPendingTransactions(): TransactionMeta[] {\n return this.#getCurrentChainTransactions().filter(\n (tx) =>\n tx.status === TransactionStatus.submitted &&\n !tx.verifiedOnBlockchain &&\n !tx.isUserOperation,\n );\n }\n\n #warnTransaction(txMeta: TransactionMeta, error: string, message: string) {\n this.#updateTransaction(\n {\n ...txMeta,\n warning: { error, message },\n },\n 'PendingTransactionTracker:#warnTransaction - Warning added',\n );\n }\n\n #failTransaction(txMeta: TransactionMeta, error: Error) {\n log('Transaction failed', txMeta.id, error);\n this.hub.emit('transaction-failed', txMeta, error);\n }\n\n #dropTransaction(txMeta: TransactionMeta) {\n log('Transaction dropped', txMeta.id);\n this.hub.emit('transaction-dropped', txMeta);\n }\n\n #updateTransaction(txMeta: TransactionMeta, note: string) {\n this.hub.emit('transaction-updated', txMeta, note);\n }\n\n async #getTransactionReceipt(\n txHash?: string,\n ): Promise {\n return await query(this.#getEthQuery(), 'getTransactionReceipt', [txHash]);\n }\n\n async #getBlockByHash(\n blockHash: string,\n includeTransactionDetails: boolean,\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): Promise {\n return await query(this.#getEthQuery(), 'getBlockByHash', [\n blockHash,\n includeTransactionDetails,\n ]);\n }\n\n async #getNetworkTransactionCount(address: string): Promise {\n return await query(this.#getEthQuery(), 'getTransactionCount', [address]);\n }\n\n #getCurrentChainTransactions(): TransactionMeta[] {\n const currentChainId = this.#getChainId();\n\n return this.#getTransactions().filter(\n (tx) => tx.chainId === currentChainId,\n );\n }\n}\n"]}
+\ No newline at end of file
+diff --git a/dist/chunk-7M2R5AHC.mjs b/dist/chunk-7M2R5AHC.mjs
+new file mode 100644
+index 0000000000000000000000000000000000000000..3b137fe1e719807e859ca036c76ffff8c234f964
+--- /dev/null
++++ b/dist/chunk-7M2R5AHC.mjs
+@@ -0,0 +1,390 @@
++import {
++ createModuleLogger,
++ projectLogger
++} from "./chunk-UQQWZT6C.mjs";
++import {
++ __privateAdd,
++ __privateGet,
++ __privateMethod,
++ __privateSet
++} from "./chunk-XUI43LEZ.mjs";
++
++// src/helpers/PendingTransactionTracker.ts
++import { query } from "@metamask/controller-utils";
++import EventEmitter from "events";
++import { cloneDeep, merge } from "lodash";
++var DROPPED_BLOCK_COUNT = 3;
++var RECEIPT_STATUS_SUCCESS = "0x1";
++var RECEIPT_STATUS_FAILURE = "0x0";
++var MAX_RETRY_BLOCK_DISTANCE = 50;
++var KNOWN_TRANSACTION_ERRORS = [
++ "replacement transaction underpriced",
++ "known transaction",
++ "gas price too low to replace",
++ "transaction with the same hash was already imported",
++ "gateway timeout",
++ "nonce too low"
++];
++var log = createModuleLogger(projectLogger, "pending-transactions");
++var _blockTracker, _droppedBlockCountByHash, _getChainId, _getEthQuery, _getTransactions, _isResubmitEnabled, _listener, _getGlobalLock, _publishTransaction, _running, _beforeCheckPendingTransaction, _beforePublish, _start, start_fn, _onLatestBlock, onLatestBlock_fn, _checkTransactions, checkTransactions_fn, _resubmitTransactions, resubmitTransactions_fn, _isKnownTransactionError, isKnownTransactionError_fn, _resubmitTransaction, resubmitTransaction_fn, _isResubmitDue, isResubmitDue_fn, _checkTransaction, checkTransaction_fn, _onTransactionConfirmed, onTransactionConfirmed_fn, _isTransactionDropped, isTransactionDropped_fn, _isNonceTaken, isNonceTaken_fn, _getPendingTransactions, getPendingTransactions_fn, _warnTransaction, warnTransaction_fn, _failTransaction, failTransaction_fn, _dropTransaction, dropTransaction_fn, _updateTransaction, updateTransaction_fn, _getTransactionReceipt, getTransactionReceipt_fn, _getBlockByHash, getBlockByHash_fn, _getNetworkTransactionCount, getNetworkTransactionCount_fn, _getCurrentChainTransactions, getCurrentChainTransactions_fn;
++var PendingTransactionTracker = class {
++ constructor({
++ blockTracker,
++ getChainId,
++ getEthQuery,
++ getTransactions,
++ isResubmitEnabled,
++ getGlobalLock,
++ publishTransaction,
++ hooks
++ }) {
++ __privateAdd(this, _start);
++ __privateAdd(this, _onLatestBlock);
++ __privateAdd(this, _checkTransactions);
++ __privateAdd(this, _resubmitTransactions);
++ __privateAdd(this, _isKnownTransactionError);
++ __privateAdd(this, _resubmitTransaction);
++ __privateAdd(this, _isResubmitDue);
++ __privateAdd(this, _checkTransaction);
++ __privateAdd(this, _onTransactionConfirmed);
++ __privateAdd(this, _isTransactionDropped);
++ __privateAdd(this, _isNonceTaken);
++ __privateAdd(this, _getPendingTransactions);
++ __privateAdd(this, _warnTransaction);
++ __privateAdd(this, _failTransaction);
++ __privateAdd(this, _dropTransaction);
++ __privateAdd(this, _updateTransaction);
++ __privateAdd(this, _getTransactionReceipt);
++ __privateAdd(this, _getBlockByHash);
++ __privateAdd(this, _getNetworkTransactionCount);
++ __privateAdd(this, _getCurrentChainTransactions);
++ __privateAdd(this, _blockTracker, void 0);
++ __privateAdd(this, _droppedBlockCountByHash, void 0);
++ __privateAdd(this, _getChainId, void 0);
++ __privateAdd(this, _getEthQuery, void 0);
++ __privateAdd(this, _getTransactions, void 0);
++ __privateAdd(this, _isResubmitEnabled, void 0);
++ // TODO: Replace `any` with type
++ // eslint-disable-next-line @typescript-eslint/no-explicit-any
++ __privateAdd(this, _listener, void 0);
++ __privateAdd(this, _getGlobalLock, void 0);
++ __privateAdd(this, _publishTransaction, void 0);
++ __privateAdd(this, _running, void 0);
++ __privateAdd(this, _beforeCheckPendingTransaction, void 0);
++ __privateAdd(this, _beforePublish, void 0);
++ this.startIfPendingTransactions = () => {
++ const pendingTransactions = __privateMethod(this, _getPendingTransactions, getPendingTransactions_fn).call(this);
++ if (pendingTransactions.length) {
++ __privateMethod(this, _start, start_fn).call(this);
++ } else {
++ this.stop();
++ }
++ };
++ this.hub = new EventEmitter();
++ __privateSet(this, _blockTracker, blockTracker);
++ __privateSet(this, _droppedBlockCountByHash, /* @__PURE__ */ new Map());
++ __privateSet(this, _getChainId, getChainId);
++ __privateSet(this, _getEthQuery, getEthQuery);
++ __privateSet(this, _getTransactions, getTransactions);
++ __privateSet(this, _isResubmitEnabled, isResubmitEnabled ?? (() => true));
++ __privateSet(this, _listener, __privateMethod(this, _onLatestBlock, onLatestBlock_fn).bind(this));
++ __privateSet(this, _getGlobalLock, getGlobalLock);
++ __privateSet(this, _publishTransaction, publishTransaction);
++ __privateSet(this, _running, false);
++ __privateSet(this, _beforePublish, hooks?.beforePublish ?? (() => true));
++ __privateSet(this, _beforeCheckPendingTransaction, hooks?.beforeCheckPendingTransaction ?? (() => true));
++ }
++ /**
++ * Force checks the network if the given transaction is confirmed and updates it's status.
++ *
++ * @param txMeta - The transaction to check
++ */
++ async forceCheckTransaction(txMeta) {
++ const releaseLock = await __privateGet(this, _getGlobalLock).call(this);
++ try {
++ await __privateMethod(this, _checkTransaction, checkTransaction_fn).call(this, txMeta);
++ } catch (error) {
++ log("Failed to check transaction", error);
++ } finally {
++ releaseLock();
++ }
++ }
++ stop() {
++ if (!__privateGet(this, _running)) {
++ return;
++ }
++ __privateGet(this, _blockTracker).removeListener("latest", __privateGet(this, _listener));
++ __privateSet(this, _running, false);
++ log("Stopped polling");
++ }
++};
++_blockTracker = new WeakMap();
++_droppedBlockCountByHash = new WeakMap();
++_getChainId = new WeakMap();
++_getEthQuery = new WeakMap();
++_getTransactions = new WeakMap();
++_isResubmitEnabled = new WeakMap();
++_listener = new WeakMap();
++_getGlobalLock = new WeakMap();
++_publishTransaction = new WeakMap();
++_running = new WeakMap();
++_beforeCheckPendingTransaction = new WeakMap();
++_beforePublish = new WeakMap();
++_start = new WeakSet();
++start_fn = function() {
++ if (__privateGet(this, _running)) {
++ return;
++ }
++ __privateGet(this, _blockTracker).on("latest", __privateGet(this, _listener));
++ __privateSet(this, _running, true);
++ log("Started polling");
++};
++_onLatestBlock = new WeakSet();
++onLatestBlock_fn = async function(latestBlockNumber) {
++ const releaseLock = await __privateGet(this, _getGlobalLock).call(this);
++ try {
++ await __privateMethod(this, _checkTransactions, checkTransactions_fn).call(this);
++ } catch (error) {
++ log("Failed to check transactions", error);
++ } finally {
++ releaseLock();
++ }
++ try {
++ await __privateMethod(this, _resubmitTransactions, resubmitTransactions_fn).call(this, latestBlockNumber);
++ } catch (error) {
++ log("Failed to resubmit transactions", error);
++ }
++};
++_checkTransactions = new WeakSet();
++checkTransactions_fn = async function() {
++ log("Checking transactions");
++ const pendingTransactions = __privateMethod(this, _getPendingTransactions, getPendingTransactions_fn).call(this);
++ if (!pendingTransactions.length) {
++ log("No pending transactions to check");
++ return;
++ }
++ log("Found pending transactions to check", {
++ count: pendingTransactions.length,
++ ids: pendingTransactions.map((tx) => tx.id)
++ });
++ await Promise.all(
++ pendingTransactions.map((tx) => __privateMethod(this, _checkTransaction, checkTransaction_fn).call(this, tx))
++ );
++};
++_resubmitTransactions = new WeakSet();
++resubmitTransactions_fn = async function(latestBlockNumber) {
++ if (!__privateGet(this, _isResubmitEnabled).call(this) || !__privateGet(this, _running)) {
++ return;
++ }
++ log("Resubmitting transactions");
++ const pendingTransactions = __privateMethod(this, _getPendingTransactions, getPendingTransactions_fn).call(this);
++ if (!pendingTransactions.length) {
++ log("No pending transactions to resubmit");
++ return;
++ }
++ log("Found pending transactions to resubmit", {
++ count: pendingTransactions.length,
++ ids: pendingTransactions.map((tx) => tx.id)
++ });
++ for (const txMeta of pendingTransactions) {
++ try {
++ await __privateMethod(this, _resubmitTransaction, resubmitTransaction_fn).call(this, txMeta, latestBlockNumber);
++ } catch (error) {
++ const errorMessage = error.value?.message?.toLowerCase() || error.message?.toLowerCase() || String(error);
++ if (__privateMethod(this, _isKnownTransactionError, isKnownTransactionError_fn).call(this, errorMessage)) {
++ log("Ignoring known transaction error", errorMessage);
++ continue;
++ }
++ __privateMethod(this, _warnTransaction, warnTransaction_fn).call(this, txMeta, error.message, "There was an error when resubmitting this transaction.");
++ }
++ }
++};
++_isKnownTransactionError = new WeakSet();
++isKnownTransactionError_fn = function(errorMessage) {
++ return KNOWN_TRANSACTION_ERRORS.some(
++ (knownError) => errorMessage.includes(knownError)
++ );
++};
++_resubmitTransaction = new WeakSet();
++resubmitTransaction_fn = async function(txMeta, latestBlockNumber) {
++ if (!__privateMethod(this, _isResubmitDue, isResubmitDue_fn).call(this, txMeta, latestBlockNumber)) {
++ return;
++ }
++ const { rawTx } = txMeta;
++ if (!__privateGet(this, _beforePublish).call(this, txMeta)) {
++ return;
++ }
++ const ethQuery = __privateGet(this, _getEthQuery).call(this, txMeta.networkClientId);
++ await __privateGet(this, _publishTransaction).call(this, ethQuery, rawTx);
++ const retryCount = (txMeta.retryCount ?? 0) + 1;
++ __privateMethod(this, _updateTransaction, updateTransaction_fn).call(this, merge({}, txMeta, { retryCount }), "PendingTransactionTracker:transaction-retry - Retry count increased");
++};
++_isResubmitDue = new WeakSet();
++isResubmitDue_fn = function(txMeta, latestBlockNumber) {
++ const txMetaWithFirstRetryBlockNumber = cloneDeep(txMeta);
++ if (!txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber) {
++ txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber = latestBlockNumber;
++ __privateMethod(this, _updateTransaction, updateTransaction_fn).call(this, txMetaWithFirstRetryBlockNumber, "PendingTransactionTracker:#isResubmitDue - First retry block number set");
++ }
++ const { firstRetryBlockNumber } = txMetaWithFirstRetryBlockNumber;
++ const blocksSinceFirstRetry = Number.parseInt(latestBlockNumber, 16) - Number.parseInt(firstRetryBlockNumber, 16);
++ const retryCount = txMeta.retryCount || 0;
++ const requiredBlocksSinceFirstRetry = Math.min(
++ MAX_RETRY_BLOCK_DISTANCE,
++ Math.pow(2, retryCount)
++ );
++ return blocksSinceFirstRetry >= requiredBlocksSinceFirstRetry;
++};
++_checkTransaction = new WeakSet();
++checkTransaction_fn = async function(txMeta) {
++ const { hash, id } = txMeta;
++ if (!hash && __privateGet(this, _beforeCheckPendingTransaction).call(this, txMeta)) {
++ const error = new Error(
++ "We had an error while submitting this transaction, please try again."
++ );
++ error.name = "NoTxHashError";
++ __privateMethod(this, _failTransaction, failTransaction_fn).call(this, txMeta, error);
++ return;
++ }
++ if (__privateMethod(this, _isNonceTaken, isNonceTaken_fn).call(this, txMeta)) {
++ log("Nonce already taken", id);
++ __privateMethod(this, _dropTransaction, dropTransaction_fn).call(this, txMeta);
++ return;
++ }
++ try {
++ const receipt = await __privateMethod(this, _getTransactionReceipt, getTransactionReceipt_fn).call(this, hash);
++ const isSuccess = receipt?.status === RECEIPT_STATUS_SUCCESS;
++ const isFailure = receipt?.status === RECEIPT_STATUS_FAILURE;
++ if (isFailure) {
++ log("Transaction receipt has failed status");
++ __privateMethod(this, _failTransaction, failTransaction_fn).call(this, txMeta, new Error("Transaction dropped or replaced"));
++ return;
++ }
++ const { blockNumber, blockHash } = receipt || {};
++ if (isSuccess && blockNumber && blockHash) {
++ await __privateMethod(this, _onTransactionConfirmed, onTransactionConfirmed_fn).call(this, txMeta, {
++ ...receipt,
++ blockNumber,
++ blockHash
++ });
++ return;
++ }
++ } catch (error) {
++ log("Failed to check transaction", id, error);
++ __privateMethod(this, _warnTransaction, warnTransaction_fn).call(this, txMeta, error.message, "There was a problem loading this transaction.");
++ return;
++ }
++ if (await __privateMethod(this, _isTransactionDropped, isTransactionDropped_fn).call(this, txMeta)) {
++ __privateMethod(this, _dropTransaction, dropTransaction_fn).call(this, txMeta);
++ }
++};
++_onTransactionConfirmed = new WeakSet();
++onTransactionConfirmed_fn = async function(txMeta, receipt) {
++ const { id } = txMeta;
++ const { blockHash } = receipt;
++ log("Transaction confirmed", id);
++ const { baseFeePerGas, timestamp: blockTimestamp } = await __privateMethod(this, _getBlockByHash, getBlockByHash_fn).call(this, blockHash, false);
++ const updatedTxMeta = cloneDeep(txMeta);
++ updatedTxMeta.baseFeePerGas = baseFeePerGas;
++ updatedTxMeta.blockTimestamp = blockTimestamp;
++ updatedTxMeta.status = "confirmed" /* confirmed */;
++ updatedTxMeta.txParams = {
++ ...updatedTxMeta.txParams,
++ gasUsed: receipt.gasUsed
++ };
++ updatedTxMeta.txReceipt = receipt;
++ updatedTxMeta.verifiedOnBlockchain = true;
++ __privateMethod(this, _updateTransaction, updateTransaction_fn).call(this, updatedTxMeta, "PendingTransactionTracker:#onTransactionConfirmed - Transaction confirmed");
++ this.hub.emit("transaction-confirmed", updatedTxMeta);
++};
++_isTransactionDropped = new WeakSet();
++isTransactionDropped_fn = async function(txMeta) {
++ const {
++ hash,
++ id,
++ txParams: { nonce, from }
++ } = txMeta;
++ if (!nonce || !hash) {
++ return false;
++ }
++ const networkNextNonceHex = await __privateMethod(this, _getNetworkTransactionCount, getNetworkTransactionCount_fn).call(this, from);
++ const networkNextNonceNumber = parseInt(networkNextNonceHex, 16);
++ const nonceNumber = parseInt(nonce, 16);
++ if (nonceNumber >= networkNextNonceNumber) {
++ return false;
++ }
++ let droppedBlockCount = __privateGet(this, _droppedBlockCountByHash).get(hash);
++ if (droppedBlockCount === void 0) {
++ droppedBlockCount = 0;
++ __privateGet(this, _droppedBlockCountByHash).set(hash, droppedBlockCount);
++ }
++ if (droppedBlockCount < DROPPED_BLOCK_COUNT) {
++ log("Incrementing dropped block count", { id, droppedBlockCount });
++ __privateGet(this, _droppedBlockCountByHash).set(hash, droppedBlockCount + 1);
++ return false;
++ }
++ log("Hit dropped block count", id);
++ __privateGet(this, _droppedBlockCountByHash).delete(hash);
++ return true;
++};
++_isNonceTaken = new WeakSet();
++isNonceTaken_fn = function(txMeta) {
++ const { id, txParams } = txMeta;
++ return __privateMethod(this, _getCurrentChainTransactions, getCurrentChainTransactions_fn).call(this).some(
++ (tx) => tx.id !== id && tx.txParams.from === txParams.from && tx.status === "confirmed" /* confirmed */ && tx.txParams.nonce === txParams.nonce && tx.type !== "incoming" /* incoming */
++ );
++};
++_getPendingTransactions = new WeakSet();
++getPendingTransactions_fn = function() {
++ return __privateMethod(this, _getCurrentChainTransactions, getCurrentChainTransactions_fn).call(this).filter(
++ (tx) => tx.status === "submitted" /* submitted */ && !tx.verifiedOnBlockchain && !tx.isUserOperation
++ );
++};
++_warnTransaction = new WeakSet();
++warnTransaction_fn = function(txMeta, error, message) {
++ __privateMethod(this, _updateTransaction, updateTransaction_fn).call(this, {
++ ...txMeta,
++ warning: { error, message }
++ }, "PendingTransactionTracker:#warnTransaction - Warning added");
++};
++_failTransaction = new WeakSet();
++failTransaction_fn = function(txMeta, error) {
++ log("Transaction failed", txMeta.id, error);
++ this.hub.emit("transaction-failed", txMeta, error);
++};
++_dropTransaction = new WeakSet();
++dropTransaction_fn = function(txMeta) {
++ log("Transaction dropped", txMeta.id);
++ this.hub.emit("transaction-dropped", txMeta);
++};
++_updateTransaction = new WeakSet();
++updateTransaction_fn = function(txMeta, note) {
++ this.hub.emit("transaction-updated", txMeta, note);
++};
++_getTransactionReceipt = new WeakSet();
++getTransactionReceipt_fn = async function(txHash) {
++ return await query(__privateGet(this, _getEthQuery).call(this), "getTransactionReceipt", [txHash]);
++};
++_getBlockByHash = new WeakSet();
++getBlockByHash_fn = async function(blockHash, includeTransactionDetails) {
++ return await query(__privateGet(this, _getEthQuery).call(this), "getBlockByHash", [
++ blockHash,
++ includeTransactionDetails
++ ]);
++};
++_getNetworkTransactionCount = new WeakSet();
++getNetworkTransactionCount_fn = async function(address) {
++ return await query(__privateGet(this, _getEthQuery).call(this), "getTransactionCount", [address]);
++};
++_getCurrentChainTransactions = new WeakSet();
++getCurrentChainTransactions_fn = function() {
++ const currentChainId = __privateGet(this, _getChainId).call(this);
++ return __privateGet(this, _getTransactions).call(this).filter(
++ (tx) => tx.chainId === currentChainId
++ );
++};
++
++export {
++ PendingTransactionTracker
++};
++//# sourceMappingURL=chunk-7M2R5AHC.mjs.map
+\ No newline at end of file
+diff --git a/dist/chunk-7M2R5AHC.mjs.map b/dist/chunk-7M2R5AHC.mjs.map
+new file mode 100644
+index 0000000000000000000000000000000000000000..bbde7a01b69392362c7c39c97ef83bd8ebefd4a1
+--- /dev/null
++++ b/dist/chunk-7M2R5AHC.mjs.map
+@@ -0,0 +1 @@
++{"version":3,"sources":["../src/helpers/PendingTransactionTracker.ts"],"sourcesContent":["import { query } from '@metamask/controller-utils';\nimport type EthQuery from '@metamask/eth-query';\nimport type {\n BlockTracker,\n NetworkClientId,\n} from '@metamask/network-controller';\nimport EventEmitter from 'events';\nimport { cloneDeep, merge } from 'lodash';\n\nimport { createModuleLogger, projectLogger } from '../logger';\nimport type { TransactionMeta, TransactionReceipt } from '../types';\nimport { TransactionStatus, TransactionType } from '../types';\n\n/**\n * We wait this many blocks before emitting a 'transaction-dropped' event\n * This is because we could be talking to a node that is out of sync\n */\nconst DROPPED_BLOCK_COUNT = 3;\n\nconst RECEIPT_STATUS_SUCCESS = '0x1';\nconst RECEIPT_STATUS_FAILURE = '0x0';\nconst MAX_RETRY_BLOCK_DISTANCE = 50;\n\nconst KNOWN_TRANSACTION_ERRORS = [\n 'replacement transaction underpriced',\n 'known transaction',\n 'gas price too low to replace',\n 'transaction with the same hash was already imported',\n 'gateway timeout',\n 'nonce too low',\n];\n\nconst log = createModuleLogger(projectLogger, 'pending-transactions');\n\ntype SuccessfulTransactionReceipt = TransactionReceipt & {\n blockNumber: string;\n blockHash: string;\n};\n\ntype Events = {\n 'transaction-confirmed': [txMeta: TransactionMeta];\n 'transaction-dropped': [txMeta: TransactionMeta];\n 'transaction-failed': [txMeta: TransactionMeta, error: Error];\n 'transaction-updated': [txMeta: TransactionMeta, note: string];\n};\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface PendingTransactionTrackerEventEmitter extends EventEmitter {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n on(\n eventName: T,\n listener: (...args: Events[T]) => void,\n ): this;\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n emit(eventName: T, ...args: Events[T]): boolean;\n}\n\nexport class PendingTransactionTracker {\n hub: PendingTransactionTrackerEventEmitter;\n\n #blockTracker: BlockTracker;\n\n #droppedBlockCountByHash: Map;\n\n #getChainId: () => string;\n\n #getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n\n #getTransactions: () => TransactionMeta[];\n\n #isResubmitEnabled: () => boolean;\n\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #listener: any;\n\n #getGlobalLock: () => Promise<() => void>;\n\n #publishTransaction: (ethQuery: EthQuery, rawTx: string) => Promise;\n\n #running: boolean;\n\n #beforeCheckPendingTransaction: (transactionMeta: TransactionMeta) => boolean;\n\n #beforePublish: (transactionMeta: TransactionMeta) => boolean;\n\n constructor({\n blockTracker,\n getChainId,\n getEthQuery,\n getTransactions,\n isResubmitEnabled,\n getGlobalLock,\n publishTransaction,\n hooks,\n }: {\n blockTracker: BlockTracker;\n getChainId: () => string;\n getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;\n getTransactions: () => TransactionMeta[];\n isResubmitEnabled?: () => boolean;\n getGlobalLock: () => Promise<() => void>;\n publishTransaction: (ethQuery: EthQuery, rawTx: string) => Promise;\n hooks?: {\n beforeCheckPendingTransaction?: (\n transactionMeta: TransactionMeta,\n ) => boolean;\n beforePublish?: (transactionMeta: TransactionMeta) => boolean;\n };\n }) {\n this.hub = new EventEmitter() as PendingTransactionTrackerEventEmitter;\n\n this.#blockTracker = blockTracker;\n this.#droppedBlockCountByHash = new Map();\n this.#getChainId = getChainId;\n this.#getEthQuery = getEthQuery;\n this.#getTransactions = getTransactions;\n this.#isResubmitEnabled = isResubmitEnabled ?? (() => true);\n this.#listener = this.#onLatestBlock.bind(this);\n this.#getGlobalLock = getGlobalLock;\n this.#publishTransaction = publishTransaction;\n this.#running = false;\n this.#beforePublish = hooks?.beforePublish ?? (() => true);\n this.#beforeCheckPendingTransaction =\n hooks?.beforeCheckPendingTransaction ?? (() => true);\n }\n\n startIfPendingTransactions = () => {\n const pendingTransactions = this.#getPendingTransactions();\n\n if (pendingTransactions.length) {\n this.#start();\n } else {\n this.stop();\n }\n };\n\n /**\n * Force checks the network if the given transaction is confirmed and updates it's status.\n *\n * @param txMeta - The transaction to check\n */\n async forceCheckTransaction(txMeta: TransactionMeta) {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransaction(txMeta);\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to check transaction', error);\n } finally {\n releaseLock();\n }\n }\n\n #start() {\n if (this.#running) {\n return;\n }\n\n this.#blockTracker.on('latest', this.#listener);\n this.#running = true;\n\n log('Started polling');\n }\n\n stop() {\n if (!this.#running) {\n return;\n }\n\n this.#blockTracker.removeListener('latest', this.#listener);\n this.#running = false;\n\n log('Stopped polling');\n }\n\n async #onLatestBlock(latestBlockNumber: string) {\n const releaseLock = await this.#getGlobalLock();\n\n try {\n await this.#checkTransactions();\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to check transactions', error);\n } finally {\n releaseLock();\n }\n\n try {\n await this.#resubmitTransactions(latestBlockNumber);\n } catch (error) {\n /* istanbul ignore next */\n log('Failed to resubmit transactions', error);\n }\n }\n\n async #checkTransactions() {\n log('Checking transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n log('No pending transactions to check');\n return;\n }\n\n log('Found pending transactions to check', {\n count: pendingTransactions.length,\n ids: pendingTransactions.map((tx) => tx.id),\n });\n\n await Promise.all(\n pendingTransactions.map((tx) => this.#checkTransaction(tx)),\n );\n }\n\n async #resubmitTransactions(latestBlockNumber: string) {\n if (!this.#isResubmitEnabled() || !this.#running) {\n return;\n }\n\n log('Resubmitting transactions');\n\n const pendingTransactions = this.#getPendingTransactions();\n\n if (!pendingTransactions.length) {\n log('No pending transactions to resubmit');\n return;\n }\n\n log('Found pending transactions to resubmit', {\n count: pendingTransactions.length,\n ids: pendingTransactions.map((tx) => tx.id),\n });\n\n for (const txMeta of pendingTransactions) {\n try {\n await this.#resubmitTransaction(txMeta, latestBlockNumber);\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n /* istanbul ignore next */\n const errorMessage =\n error.value?.message?.toLowerCase() ||\n error.message?.toLowerCase() ||\n String(error);\n\n if (this.#isKnownTransactionError(errorMessage)) {\n log('Ignoring known transaction error', errorMessage);\n continue;\n }\n\n this.#warnTransaction(\n txMeta,\n error.message,\n 'There was an error when resubmitting this transaction.',\n );\n }\n }\n }\n\n #isKnownTransactionError(errorMessage: string) {\n return KNOWN_TRANSACTION_ERRORS.some((knownError) =>\n errorMessage.includes(knownError),\n );\n }\n\n async #resubmitTransaction(\n txMeta: TransactionMeta,\n latestBlockNumber: string,\n ) {\n if (!this.#isResubmitDue(txMeta, latestBlockNumber)) {\n return;\n }\n\n const { rawTx } = txMeta;\n\n if (!this.#beforePublish(txMeta)) {\n return;\n }\n\n const ethQuery = this.#getEthQuery(txMeta.networkClientId);\n await this.#publishTransaction(ethQuery, rawTx as string);\n\n const retryCount = (txMeta.retryCount ?? 0) + 1;\n\n this.#updateTransaction(\n merge({}, txMeta, { retryCount }),\n 'PendingTransactionTracker:transaction-retry - Retry count increased',\n );\n }\n\n #isResubmitDue(txMeta: TransactionMeta, latestBlockNumber: string): boolean {\n const txMetaWithFirstRetryBlockNumber = cloneDeep(txMeta);\n\n if (!txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber) {\n txMetaWithFirstRetryBlockNumber.firstRetryBlockNumber = latestBlockNumber;\n\n this.#updateTransaction(\n txMetaWithFirstRetryBlockNumber,\n 'PendingTransactionTracker:#isResubmitDue - First retry block number set',\n );\n }\n\n const { firstRetryBlockNumber } = txMetaWithFirstRetryBlockNumber;\n\n const blocksSinceFirstRetry =\n Number.parseInt(latestBlockNumber, 16) -\n Number.parseInt(firstRetryBlockNumber, 16);\n\n const retryCount = txMeta.retryCount || 0;\n\n // Exponential backoff to limit retries at publishing\n // Capped at ~15 minutes between retries\n const requiredBlocksSinceFirstRetry = Math.min(\n MAX_RETRY_BLOCK_DISTANCE,\n Math.pow(2, retryCount),\n );\n\n return blocksSinceFirstRetry >= requiredBlocksSinceFirstRetry;\n }\n\n async #checkTransaction(txMeta: TransactionMeta) {\n const { hash, id } = txMeta;\n\n if (!hash && this.#beforeCheckPendingTransaction(txMeta)) {\n const error = new Error(\n 'We had an error while submitting this transaction, please try again.',\n );\n\n error.name = 'NoTxHashError';\n\n this.#failTransaction(txMeta, error);\n\n return;\n }\n\n if (this.#isNonceTaken(txMeta)) {\n log('Nonce already taken', id);\n this.#dropTransaction(txMeta);\n return;\n }\n\n try {\n const receipt = await this.#getTransactionReceipt(hash);\n const isSuccess = receipt?.status === RECEIPT_STATUS_SUCCESS;\n const isFailure = receipt?.status === RECEIPT_STATUS_FAILURE;\n\n if (isFailure) {\n log('Transaction receipt has failed status');\n\n this.#failTransaction(\n txMeta,\n new Error('Transaction dropped or replaced'),\n );\n\n return;\n }\n\n const { blockNumber, blockHash } = receipt || {};\n\n if (isSuccess && blockNumber && blockHash) {\n await this.#onTransactionConfirmed(txMeta, {\n ...receipt,\n blockNumber,\n blockHash,\n });\n\n return;\n }\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n log('Failed to check transaction', id, error);\n\n this.#warnTransaction(\n txMeta,\n error.message,\n 'There was a problem loading this transaction.',\n );\n\n return;\n }\n\n if (await this.#isTransactionDropped(txMeta)) {\n this.#dropTransaction(txMeta);\n }\n }\n\n async #onTransactionConfirmed(\n txMeta: TransactionMeta,\n receipt: SuccessfulTransactionReceipt,\n ) {\n const { id } = txMeta;\n const { blockHash } = receipt;\n\n log('Transaction confirmed', id);\n\n const { baseFeePerGas, timestamp: blockTimestamp } =\n await this.#getBlockByHash(blockHash, false);\n\n const updatedTxMeta = cloneDeep(txMeta);\n updatedTxMeta.baseFeePerGas = baseFeePerGas;\n updatedTxMeta.blockTimestamp = blockTimestamp;\n updatedTxMeta.status = TransactionStatus.confirmed;\n updatedTxMeta.txParams = {\n ...updatedTxMeta.txParams,\n gasUsed: receipt.gasUsed,\n };\n updatedTxMeta.txReceipt = receipt;\n updatedTxMeta.verifiedOnBlockchain = true;\n\n this.#updateTransaction(\n updatedTxMeta,\n 'PendingTransactionTracker:#onTransactionConfirmed - Transaction confirmed',\n );\n\n this.hub.emit('transaction-confirmed', updatedTxMeta);\n }\n\n async #isTransactionDropped(txMeta: TransactionMeta) {\n const {\n hash,\n id,\n txParams: { nonce, from },\n } = txMeta;\n\n /* istanbul ignore next */\n if (!nonce || !hash) {\n return false;\n }\n\n const networkNextNonceHex = await this.#getNetworkTransactionCount(from);\n const networkNextNonceNumber = parseInt(networkNextNonceHex, 16);\n const nonceNumber = parseInt(nonce, 16);\n\n if (nonceNumber >= networkNextNonceNumber) {\n return false;\n }\n\n let droppedBlockCount = this.#droppedBlockCountByHash.get(hash);\n\n if (droppedBlockCount === undefined) {\n droppedBlockCount = 0;\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount);\n }\n\n if (droppedBlockCount < DROPPED_BLOCK_COUNT) {\n log('Incrementing dropped block count', { id, droppedBlockCount });\n this.#droppedBlockCountByHash.set(hash, droppedBlockCount + 1);\n return false;\n }\n\n log('Hit dropped block count', id);\n\n this.#droppedBlockCountByHash.delete(hash);\n return true;\n }\n\n #isNonceTaken(txMeta: TransactionMeta): boolean {\n const { id, txParams } = txMeta;\n\n return this.#getCurrentChainTransactions().some(\n (tx) =>\n tx.id !== id &&\n tx.txParams.from === txParams.from &&\n tx.status === TransactionStatus.confirmed &&\n tx.txParams.nonce === txParams.nonce &&\n tx.type !== TransactionType.incoming,\n );\n }\n\n #getPendingTransactions(): TransactionMeta[] {\n return this.#getCurrentChainTransactions().filter(\n (tx) =>\n tx.status === TransactionStatus.submitted &&\n !tx.verifiedOnBlockchain &&\n !tx.isUserOperation,\n );\n }\n\n #warnTransaction(txMeta: TransactionMeta, error: string, message: string) {\n this.#updateTransaction(\n {\n ...txMeta,\n warning: { error, message },\n },\n 'PendingTransactionTracker:#warnTransaction - Warning added',\n );\n }\n\n #failTransaction(txMeta: TransactionMeta, error: Error) {\n log('Transaction failed', txMeta.id, error);\n this.hub.emit('transaction-failed', txMeta, error);\n }\n\n #dropTransaction(txMeta: TransactionMeta) {\n log('Transaction dropped', txMeta.id);\n this.hub.emit('transaction-dropped', txMeta);\n }\n\n #updateTransaction(txMeta: TransactionMeta, note: string) {\n this.hub.emit('transaction-updated', txMeta, note);\n }\n\n async #getTransactionReceipt(\n txHash?: string,\n ): Promise {\n return await query(this.#getEthQuery(), 'getTransactionReceipt', [txHash]);\n }\n\n async #getBlockByHash(\n blockHash: string,\n includeTransactionDetails: boolean,\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ): Promise {\n return await query(this.#getEthQuery(), 'getBlockByHash', [\n blockHash,\n includeTransactionDetails,\n ]);\n }\n\n async #getNetworkTransactionCount(address: string): Promise {\n return await query(this.#getEthQuery(), 'getTransactionCount', [address]);\n }\n\n #getCurrentChainTransactions(): TransactionMeta[] {\n const currentChainId = this.#getChainId();\n\n return this.#getTransactions().filter(\n (tx) => tx.chainId === currentChainId,\n );\n }\n}\n"],"mappings":"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","names":[]}
+\ No newline at end of file
+diff --git a/dist/chunk-IVR4NMOF.js b/dist/chunk-IVR4NMOF.js
+new file mode 100644
+index 0000000000000000000000000000000000000000..2266127ef5aead422d1ccf8f1a53734f81499d96
+--- /dev/null
++++ b/dist/chunk-IVR4NMOF.js
+@@ -0,0 +1,2556 @@
++"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
++
++
++var _chunkPRUNMTRDjs = require('./chunk-PRUNMTRD.js');
++
++
++var _chunk74W7X6BEjs = require('./chunk-74W7X6BE.js');
++
++
++var _chunkSD6CWFDFjs = require('./chunk-SD6CWFDF.js');
++
++
++
++var _chunkRXIUMVA5js = require('./chunk-RXIUMVA5.js');
++
++
++var _chunk6DODV6OVjs = require('./chunk-6DODV6OV.js');
++
++
++var _chunk7LXE4KHVjs = require('./chunk-7LXE4KHV.js');
++
++
++
++
++var _chunkV72C4MCRjs = require('./chunk-V72C4MCR.js');
++
++
++
++var _chunkQP75SWIQjs = require('./chunk-QP75SWIQ.js');
++
++
++var _chunkNYKRCWBGjs = require('./chunk-NYKRCWBG.js');
++
++
++var _chunkWR5F34OWjs = require('./chunk-WR5F34OW.js');
++
++
++var _chunkTJMQEH57js = require('./chunk-TJMQEH57.js');
++
++
++var _chunk2EU6346Vjs = require('./chunk-2EU6346V.js');
++
++
++
++var _chunk2XKEAKQGjs = require('./chunk-2XKEAKQG.js');
++
++
++var _chunkRHDPOIS4js = require('./chunk-RHDPOIS4.js');
++
++
++var _chunk6OLJWLKKjs = require('./chunk-6OLJWLKK.js');
++
++
++var _chunk7NMV2NPMjs = require('./chunk-7NMV2NPM.js');
++
++
++var _chunkARZHJFVGjs = require('./chunk-ARZHJFVG.js');
++
++
++var _chunkQTKXIDGEjs = require('./chunk-QTKXIDGE.js');
++
++
++var _chunkC3WC4OJ3js = require('./chunk-C3WC4OJ3.js');
++
++
++
++var _chunkQH2H4W3Njs = require('./chunk-QH2H4W3N.js');
++
++
++
++
++
++
++
++
++
++
++
++var _chunkOZ6UB42Cjs = require('./chunk-OZ6UB42C.js');
++
++
++var _chunk76FONEDAjs = require('./chunk-76FONEDA.js');
++
++
++var _chunkS6VGOPUYjs = require('./chunk-S6VGOPUY.js');
++
++
++
++
++
++var _chunkZ4BLTVTBjs = require('./chunk-Z4BLTVTB.js');
++
++// src/TransactionController.ts
++var _common = require('@ethereumjs/common');
++var _tx = require('@ethereumjs/tx');
++var _util = require('@ethereumjs/util');
++var _basecontroller = require('@metamask/base-controller');
++
++
++
++
++
++
++var _controllerutils = require('@metamask/controller-utils');
++var _ethquery = require('@metamask/eth-query'); var _ethquery2 = _interopRequireDefault(_ethquery);
++var _networkcontroller = require('@metamask/network-controller');
++var _noncetracker = require('@metamask/nonce-tracker');
++var _rpcerrors = require('@metamask/rpc-errors');
++var _utils = require('@metamask/utils');
++var _asyncmutex = require('async-mutex');
++var _ethmethodregistry = require('eth-method-registry');
++var _events = require('events');
++var _lodash = require('lodash');
++var _uuid = require('uuid');
++var metadata = {
++ transactions: {
++ persist: true,
++ anonymous: false
++ },
++ methodData: {
++ persist: true,
++ anonymous: false
++ },
++ lastFetchedBlockNumbers: {
++ persist: true,
++ anonymous: false
++ }
++};
++var HARDFORK = _common.Hardfork.London;
++var CANCEL_RATE = 1.1;
++var SPEED_UP_RATE = 1.1;
++var controllerName = "TransactionController";
++var ApprovalState = /* @__PURE__ */ ((ApprovalState2) => {
++ ApprovalState2["Approved"] = "approved";
++ ApprovalState2["NotApproved"] = "not-approved";
++ ApprovalState2["SkippedViaBeforePublishHook"] = "skipped-via-before-publish-hook";
++ return ApprovalState2;
++})(ApprovalState || {});
++function getDefaultTransactionControllerState() {
++ return {
++ methodData: {},
++ transactions: [],
++ lastFetchedBlockNumbers: {}
++ };
++}
++var _internalEvents, _incomingTransactionOptions, _pendingTransactionOptions, _transactionHistoryLimit, _isSimulationEnabled, _testGasFeeFlows, _multichainTrackingHelper, _createNonceTracker, createNonceTracker_fn, _createIncomingTransactionHelper, createIncomingTransactionHelper_fn, _createPendingTransactionTracker, createPendingTransactionTracker_fn, _checkForPendingTransactionAndStartPolling, _stopAllTracking, stopAllTracking_fn, _removeIncomingTransactionHelperListeners, removeIncomingTransactionHelperListeners_fn, _addIncomingTransactionHelperListeners, addIncomingTransactionHelperListeners_fn, _removePendingTransactionTrackerListeners, removePendingTransactionTrackerListeners_fn, _addPendingTransactionTrackerListeners, addPendingTransactionTrackerListeners_fn, _getNonceTrackerPendingTransactions, getNonceTrackerPendingTransactions_fn, _getGasFeeFlows, getGasFeeFlows_fn, _getLayer1GasFeeFlows, getLayer1GasFeeFlows_fn, _updateTransactionInternal, updateTransactionInternal_fn, _checkIfTransactionParamsUpdated, checkIfTransactionParamsUpdated_fn, _onTransactionParamsUpdated, onTransactionParamsUpdated_fn, _updateSimulationData, updateSimulationData_fn, _onGasFeePollerTransactionUpdate, onGasFeePollerTransactionUpdate_fn, _getNetworkClientId, getNetworkClientId_fn, _getGlobalNetworkClientId, getGlobalNetworkClientId_fn, _getGlobalChainId, getGlobalChainId_fn, _isCustomNetwork, isCustomNetwork_fn, _getSelectedAccount, getSelectedAccount_fn;
++var TransactionController = class extends _basecontroller.BaseController {
++ /**
++ * Constructs a TransactionController.
++ *
++ * @param options - The controller options.
++ * @param options.blockTracker - The block tracker used to poll for new blocks data.
++ * @param options.disableHistory - Whether to disable storing history in transaction metadata.
++ * @param options.disableSendFlowHistory - Explicitly disable transaction metadata history.
++ * @param options.disableSwaps - Whether to disable additional processing on swaps transactions.
++ * @param options.getCurrentAccountEIP1559Compatibility - Whether or not the account supports EIP-1559.
++ * @param options.getCurrentNetworkEIP1559Compatibility - Whether or not the network supports EIP-1559.
++ * @param options.getExternalPendingTransactions - Callback to retrieve pending transactions from external sources.
++ * @param options.getGasFeeEstimates - Callback to retrieve gas fee estimates.
++ * @param options.getNetworkClientRegistry - Gets the network client registry.
++ * @param options.getNetworkState - Gets the state of the network controller.
++ * @param options.getPermittedAccounts - Get accounts that a given origin has permissions for.
++ * @param options.getSavedGasFees - Gets the saved gas fee config.
++ * @param options.incomingTransactions - Configuration options for incoming transaction support.
++ * @param options.isMultichainEnabled - Enable multichain support.
++ * @param options.isSimulationEnabled - Whether new transactions will be automatically simulated.
++ * @param options.messenger - The controller messenger.
++ * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.
++ * @param options.pendingTransactions - Configuration options for pending transaction support.
++ * @param options.provider - The provider used to create the underlying EthQuery instance.
++ * @param options.securityProviderRequest - A function for verifying a transaction, whether it is malicious or not.
++ * @param options.sign - Function used to sign transactions.
++ * @param options.state - Initial state to set on this controller.
++ * @param options.testGasFeeFlows - Whether to use the test gas fee flow.
++ * @param options.transactionHistoryLimit - Transaction history limit.
++ * @param options.hooks - The controller hooks.
++ */
++ constructor({
++ blockTracker,
++ disableHistory,
++ disableSendFlowHistory,
++ disableSwaps,
++ getCurrentAccountEIP1559Compatibility,
++ getCurrentNetworkEIP1559Compatibility,
++ getExternalPendingTransactions,
++ getGasFeeEstimates,
++ getNetworkClientRegistry,
++ getNetworkState,
++ getPermittedAccounts,
++ getSavedGasFees,
++ incomingTransactions = {},
++ isMultichainEnabled = false,
++ isSimulationEnabled,
++ messenger,
++ onNetworkStateChange,
++ pendingTransactions = {},
++ provider,
++ securityProviderRequest,
++ sign,
++ state,
++ testGasFeeFlows,
++ transactionHistoryLimit = 40,
++ hooks
++ }) {
++ super({
++ name: controllerName,
++ metadata,
++ messenger,
++ state: {
++ ...getDefaultTransactionControllerState(),
++ ...state
++ }
++ });
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _createNonceTracker);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _createIncomingTransactionHelper);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _createPendingTransactionTracker);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _stopAllTracking);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _removeIncomingTransactionHelperListeners);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _addIncomingTransactionHelperListeners);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _removePendingTransactionTrackerListeners);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _addPendingTransactionTrackerListeners);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getNonceTrackerPendingTransactions);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getGasFeeFlows);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getLayer1GasFeeFlows);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _updateTransactionInternal);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _checkIfTransactionParamsUpdated);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _onTransactionParamsUpdated);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _updateSimulationData);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _onGasFeePollerTransactionUpdate);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getNetworkClientId);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getGlobalNetworkClientId);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getGlobalChainId);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _isCustomNetwork);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _getSelectedAccount);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _internalEvents, new (0, _events.EventEmitter)());
++ this.approvingTransactionIds = /* @__PURE__ */ new Set();
++ this.mutex = new (0, _asyncmutex.Mutex)();
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _incomingTransactionOptions, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _pendingTransactionOptions, void 0);
++ this.signAbortCallbacks = /* @__PURE__ */ new Map();
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _transactionHistoryLimit, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _isSimulationEnabled, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _testGasFeeFlows, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _multichainTrackingHelper, void 0);
++ _chunkZ4BLTVTBjs.__privateAdd.call(void 0, this, _checkForPendingTransactionAndStartPolling, () => {
++ this.pendingTransactionTracker.startIfPendingTransactions();
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).checkForPendingTransactionAndStartPolling();
++ });
++ this.messagingSystem = messenger;
++ this.getNetworkState = getNetworkState;
++ this.isSendFlowHistoryDisabled = disableSendFlowHistory ?? false;
++ this.isHistoryDisabled = disableHistory ?? false;
++ this.isSwapsDisabled = disableSwaps ?? false;
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _isSimulationEnabled, isSimulationEnabled ?? (() => true));
++ this.registry = new (0, _ethmethodregistry.MethodRegistry)({ provider });
++ this.getSavedGasFees = getSavedGasFees ?? ((_chainId) => void 0);
++ this.getCurrentAccountEIP1559Compatibility = getCurrentAccountEIP1559Compatibility ?? (() => Promise.resolve(true));
++ this.getCurrentNetworkEIP1559Compatibility = getCurrentNetworkEIP1559Compatibility;
++ this.getGasFeeEstimates = getGasFeeEstimates || (() => Promise.resolve({}));
++ this.getPermittedAccounts = getPermittedAccounts;
++ this.getExternalPendingTransactions = getExternalPendingTransactions ?? (() => []);
++ this.securityProviderRequest = securityProviderRequest;
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _incomingTransactionOptions, incomingTransactions);
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _pendingTransactionOptions, pendingTransactions);
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _transactionHistoryLimit, transactionHistoryLimit);
++ this.sign = sign;
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _testGasFeeFlows, testGasFeeFlows === true);
++ this.afterSign = hooks?.afterSign ?? (() => true);
++ this.beforeCheckPendingTransaction = hooks?.beforeCheckPendingTransaction ?? /* istanbul ignore next */
++ (() => true);
++ this.beforePublish = hooks?.beforePublish ?? (() => true);
++ this.getAdditionalSignArguments = hooks?.getAdditionalSignArguments ?? (() => []);
++ this.publish = hooks?.publish ?? (() => Promise.resolve({ transactionHash: void 0 }));
++ this.nonceTracker = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _createNonceTracker, createNonceTracker_fn).call(this, {
++ provider,
++ blockTracker
++ });
++ const findNetworkClientIdByChainId = (chainId) => {
++ return this.messagingSystem.call(
++ `NetworkController:findNetworkClientIdByChainId`,
++ chainId
++ );
++ };
++ _chunkZ4BLTVTBjs.__privateSet.call(void 0, this, _multichainTrackingHelper, new (0, _chunk6OLJWLKKjs.MultichainTrackingHelper)({
++ isMultichainEnabled,
++ provider,
++ nonceTracker: this.nonceTracker,
++ incomingTransactionOptions: incomingTransactions,
++ findNetworkClientIdByChainId,
++ getNetworkClientById: (networkClientId) => {
++ return this.messagingSystem.call(
++ `NetworkController:getNetworkClientById`,
++ networkClientId
++ );
++ },
++ getNetworkClientRegistry,
++ removeIncomingTransactionHelperListeners: _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _removeIncomingTransactionHelperListeners, removeIncomingTransactionHelperListeners_fn).bind(this),
++ removePendingTransactionTrackerListeners: _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _removePendingTransactionTrackerListeners, removePendingTransactionTrackerListeners_fn).bind(this),
++ createNonceTracker: _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _createNonceTracker, createNonceTracker_fn).bind(this),
++ createIncomingTransactionHelper: _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _createIncomingTransactionHelper, createIncomingTransactionHelper_fn).bind(this),
++ createPendingTransactionTracker: _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _createPendingTransactionTracker, createPendingTransactionTracker_fn).bind(this),
++ onNetworkStateChange: (listener) => {
++ this.messagingSystem.subscribe(
++ "NetworkController:stateChange",
++ listener
++ );
++ }
++ }));
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).initialize();
++ const etherscanRemoteTransactionSource = new (0, _chunk7NMV2NPMjs.EtherscanRemoteTransactionSource)({
++ includeTokenTransfers: incomingTransactions.includeTokenTransfers
++ });
++ this.incomingTransactionHelper = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _createIncomingTransactionHelper, createIncomingTransactionHelper_fn).call(this, {
++ blockTracker,
++ etherscanRemoteTransactionSource
++ });
++ this.pendingTransactionTracker = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _createPendingTransactionTracker, createPendingTransactionTracker_fn).call(this, {
++ provider,
++ blockTracker
++ });
++ this.gasFeeFlows = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getGasFeeFlows, getGasFeeFlows_fn).call(this);
++ this.layer1GasFeeFlows = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getLayer1GasFeeFlows, getLayer1GasFeeFlows_fn).call(this);
++ const gasFeePoller = new (0, _chunk2EU6346Vjs.GasFeePoller)({
++ findNetworkClientIdByChainId,
++ gasFeeFlows: this.gasFeeFlows,
++ getGasFeeControllerEstimates: this.getGasFeeEstimates,
++ getProvider: (chainId, networkClientId) => _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getProvider({
++ networkClientId,
++ chainId
++ }),
++ getTransactions: () => this.state.transactions,
++ layer1GasFeeFlows: this.layer1GasFeeFlows,
++ onStateChange: (listener) => {
++ this.messagingSystem.subscribe(
++ "TransactionController:stateChange",
++ listener
++ );
++ }
++ });
++ gasFeePoller.hub.on(
++ "transaction-updated",
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _onGasFeePollerTransactionUpdate, onGasFeePollerTransactionUpdate_fn).bind(this)
++ );
++ this.messagingSystem.subscribe(
++ "TransactionController:stateChange",
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _checkForPendingTransactionAndStartPolling)
++ );
++ onNetworkStateChange(() => {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Detected network change", this.getChainId());
++ this.pendingTransactionTracker.startIfPendingTransactions();
++ this.onBootCleanup();
++ });
++ this.onBootCleanup();
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _checkForPendingTransactionAndStartPolling).call(this);
++ }
++ failTransaction(transactionMeta, error, actionId) {
++ let newTransactionMeta;
++ try {
++ newTransactionMeta = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, {
++ transactionId: transactionMeta.id,
++ note: "TransactionController#failTransaction - Add error message and set status to failed",
++ skipValidation: true
++ }, (draftTransactionMeta) => {
++ draftTransactionMeta.status = "failed" /* failed */;
++ draftTransactionMeta.error = _chunkOZ6UB42Cjs.normalizeTxError.call(void 0, error);
++ });
++ } catch (err) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Failed to mark transaction as failed", err);
++ newTransactionMeta = {
++ ...transactionMeta,
++ status: "failed" /* failed */,
++ error: _chunkOZ6UB42Cjs.normalizeTxError.call(void 0, error)
++ };
++ }
++ this.messagingSystem.publish(`${controllerName}:transactionFailed`, {
++ actionId,
++ error: error.message,
++ transactionMeta: newTransactionMeta
++ });
++ this.onTransactionStatusChange(newTransactionMeta);
++ this.messagingSystem.publish(
++ `${controllerName}:transactionFinished`,
++ newTransactionMeta
++ );
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _internalEvents).emit(
++ `${transactionMeta.id}:finished`,
++ newTransactionMeta
++ );
++ }
++ async registryLookup(fourBytePrefix) {
++ const registryMethod = await this.registry.lookup(fourBytePrefix);
++ if (!registryMethod) {
++ return {
++ registryMethod: "",
++ parsedRegistryMethod: { name: void 0, args: void 0 }
++ };
++ }
++ const parsedRegistryMethod = this.registry.parse(registryMethod);
++ return { registryMethod, parsedRegistryMethod };
++ }
++ /**
++ * Stops polling and removes listeners to prepare the controller for garbage collection.
++ */
++ destroy() {
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _stopAllTracking, stopAllTracking_fn).call(this);
++ }
++ /**
++ * Handle new method data request.
++ *
++ * @param fourBytePrefix - The method prefix.
++ * @returns The method data object corresponding to the given signature prefix.
++ */
++ async handleMethodData(fourBytePrefix) {
++ const releaseLock = await this.mutex.acquire();
++ try {
++ const { methodData } = this.state;
++ const knownMethod = Object.keys(methodData).find(
++ (knownFourBytePrefix) => fourBytePrefix === knownFourBytePrefix
++ );
++ if (knownMethod) {
++ return methodData[fourBytePrefix];
++ }
++ const registry = await this.registryLookup(fourBytePrefix);
++ this.update((state) => {
++ state.methodData[fourBytePrefix] = registry;
++ });
++ return registry;
++ } finally {
++ releaseLock();
++ }
++ }
++ /**
++ * Add a new unapproved transaction to state. Parameters will be validated, a
++ * unique transaction id will be generated, and gas and gasPrice will be calculated
++ * if not provided. If A `:unapproved` hub event will be emitted once added.
++ *
++ * @param txParams - Standard parameters for an Ethereum transaction.
++ * @param opts - Additional options to control how the transaction is added.
++ * @param opts.actionId - Unique ID to prevent duplicate requests.
++ * @param opts.deviceConfirmedOn - An enum to indicate what device confirmed the transaction.
++ * @param opts.method - RPC method that requested the transaction.
++ * @param opts.origin - The origin of the transaction request, such as a dApp hostname.
++ * @param opts.requireApproval - Whether the transaction requires approval by the user, defaults to true unless explicitly disabled.
++ * @param opts.securityAlertResponse - Response from security validator.
++ * @param opts.sendFlowHistory - The sendFlowHistory entries to add.
++ * @param opts.type - Type of transaction to add, such as 'cancel' or 'swap'.
++ * @param opts.swaps - Options for swaps transactions.
++ * @param opts.swaps.hasApproveTx - Whether the transaction has an approval transaction.
++ * @param opts.swaps.meta - Metadata for swap transaction.
++ * @param opts.networkClientId - The id of the network client for this transaction.
++ * @returns Object containing a promise resolving to the transaction hash if approved.
++ */
++ async addTransaction(txParams, {
++ actionId,
++ deviceConfirmedOn,
++ method,
++ origin,
++ requireApproval,
++ securityAlertResponse,
++ sendFlowHistory,
++ swaps = {},
++ type,
++ networkClientId: requestNetworkClientId
++ } = {}) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Adding transaction", txParams);
++ txParams = _chunkOZ6UB42Cjs.normalizeTransactionParams.call(void 0, txParams);
++ if (requestNetworkClientId && !_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).has(requestNetworkClientId)) {
++ throw new Error(
++ "The networkClientId for this transaction could not be found"
++ );
++ }
++ const networkClientId = requestNetworkClientId ?? _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getGlobalNetworkClientId, getGlobalNetworkClientId_fn).call(this);
++ const isEIP1559Compatible = await this.getEIP1559Compatibility(
++ networkClientId
++ );
++ _chunkRXIUMVA5js.validateTxParams.call(void 0, txParams, isEIP1559Compatible);
++ if (origin) {
++ await _chunkRXIUMVA5js.validateTransactionOrigin.call(void 0,
++ await this.getPermittedAccounts(origin),
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getSelectedAccount, getSelectedAccount_fn).call(this).address,
++ txParams.from,
++ origin
++ );
++ }
++ const dappSuggestedGasFees = this.generateDappSuggestedGasFees(
++ txParams,
++ origin
++ );
++ const chainId = this.getChainId(networkClientId);
++ const ethQuery = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getEthQuery({
++ networkClientId,
++ chainId
++ });
++ const transactionType = type ?? (await _chunkSD6CWFDFjs.determineTransactionType.call(void 0, txParams, ethQuery)).type;
++ const existingTransactionMeta = this.getTransactionWithActionId(actionId);
++ let addedTransactionMeta = existingTransactionMeta ? _lodash.cloneDeep.call(void 0, existingTransactionMeta) : {
++ // Add actionId to txMeta to check if same actionId is seen again
++ actionId,
++ chainId,
++ dappSuggestedGasFees,
++ deviceConfirmedOn,
++ id: _uuid.v1.call(void 0, ),
++ origin,
++ securityAlertResponse,
++ status: "unapproved" /* unapproved */,
++ time: Date.now(),
++ txParams,
++ userEditedGasLimit: false,
++ verifiedOnBlockchain: false,
++ type: transactionType,
++ networkClientId
++ };
++ await this.updateGasProperties(addedTransactionMeta);
++ if (!existingTransactionMeta) {
++ if (method && this.securityProviderRequest) {
++ const securityProviderResponse = await this.securityProviderRequest(
++ addedTransactionMeta,
++ method
++ );
++ addedTransactionMeta.securityProviderResponse = securityProviderResponse;
++ }
++ if (!this.isSendFlowHistoryDisabled) {
++ addedTransactionMeta.sendFlowHistory = sendFlowHistory ?? [];
++ }
++ if (!this.isHistoryDisabled) {
++ addedTransactionMeta = _chunkQP75SWIQjs.addInitialHistorySnapshot.call(void 0, addedTransactionMeta);
++ }
++ addedTransactionMeta = _chunkQH2H4W3Njs.updateSwapsTransaction.call(void 0,
++ addedTransactionMeta,
++ transactionType,
++ swaps,
++ {
++ isSwapsDisabled: this.isSwapsDisabled,
++ cancelTransaction: this.cancelTransaction.bind(this),
++ messenger: this.messagingSystem
++ }
++ );
++ this.addMetadata(addedTransactionMeta);
++ if (requireApproval !== false) {
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateSimulationData, updateSimulationData_fn).call(this, addedTransactionMeta);
++ } else {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Skipping simulation as approval not required");
++ }
++ this.messagingSystem.publish(
++ `${controllerName}:unapprovedTransactionAdded`,
++ addedTransactionMeta
++ );
++ }
++ return {
++ result: this.processApproval(addedTransactionMeta, {
++ isExisting: Boolean(existingTransactionMeta),
++ requireApproval,
++ actionId
++ }),
++ transactionMeta: addedTransactionMeta
++ };
++ }
++ startIncomingTransactionPolling(networkClientIds = []) {
++ if (networkClientIds.length === 0) {
++ this.incomingTransactionHelper.start();
++ return;
++ }
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).startIncomingTransactionPolling(
++ networkClientIds
++ );
++ }
++ stopIncomingTransactionPolling(networkClientIds = []) {
++ if (networkClientIds.length === 0) {
++ this.incomingTransactionHelper.stop();
++ return;
++ }
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).stopIncomingTransactionPolling(
++ networkClientIds
++ );
++ }
++ stopAllIncomingTransactionPolling() {
++ this.incomingTransactionHelper.stop();
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).stopAllIncomingTransactionPolling();
++ }
++ async updateIncomingTransactions(networkClientIds = []) {
++ if (networkClientIds.length === 0) {
++ await this.incomingTransactionHelper.update();
++ return;
++ }
++ await _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).updateIncomingTransactions(
++ networkClientIds
++ );
++ }
++ /**
++ * Attempts to cancel a transaction based on its ID by setting its status to "rejected"
++ * and emitting a `:finished` hub event.
++ *
++ * @param transactionId - The ID of the transaction to cancel.
++ * @param gasValues - The gas values to use for the cancellation transaction.
++ * @param options - The options for the cancellation transaction.
++ * @param options.actionId - Unique ID to prevent duplicate requests.
++ * @param options.estimatedBaseFee - The estimated base fee of the transaction.
++ */
++ async stopTransaction(transactionId, gasValues, {
++ estimatedBaseFee,
++ actionId
++ } = {}) {
++ if (this.getTransactionWithActionId(actionId)) {
++ return;
++ }
++ if (gasValues) {
++ gasValues = _chunkOZ6UB42Cjs.normalizeGasFeeValues.call(void 0, gasValues);
++ _chunkOZ6UB42Cjs.validateGasValues.call(void 0, gasValues);
++ }
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Creating cancel transaction", transactionId, gasValues);
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ return;
++ }
++ if (!this.sign) {
++ throw new Error("No sign method defined.");
++ }
++ const minGasPrice = _chunkOZ6UB42Cjs.getIncreasedPriceFromExisting.call(void 0,
++ transactionMeta.txParams.gasPrice,
++ CANCEL_RATE
++ );
++ const gasPriceFromValues = _chunkOZ6UB42Cjs.isGasPriceValue.call(void 0, gasValues) && gasValues.gasPrice;
++ const newGasPrice = gasPriceFromValues && _chunkOZ6UB42Cjs.validateMinimumIncrease.call(void 0, gasPriceFromValues, minGasPrice) || minGasPrice;
++ const existingMaxFeePerGas = transactionMeta.txParams?.maxFeePerGas;
++ const minMaxFeePerGas = _chunkOZ6UB42Cjs.getIncreasedPriceFromExisting.call(void 0,
++ existingMaxFeePerGas,
++ CANCEL_RATE
++ );
++ const maxFeePerGasValues = _chunkOZ6UB42Cjs.isFeeMarketEIP1559Values.call(void 0, gasValues) && gasValues.maxFeePerGas;
++ const newMaxFeePerGas = maxFeePerGasValues && _chunkOZ6UB42Cjs.validateMinimumIncrease.call(void 0, maxFeePerGasValues, minMaxFeePerGas) || existingMaxFeePerGas && minMaxFeePerGas;
++ const existingMaxPriorityFeePerGas = transactionMeta.txParams?.maxPriorityFeePerGas;
++ const minMaxPriorityFeePerGas = _chunkOZ6UB42Cjs.getIncreasedPriceFromExisting.call(void 0,
++ existingMaxPriorityFeePerGas,
++ CANCEL_RATE
++ );
++ const maxPriorityFeePerGasValues = _chunkOZ6UB42Cjs.isFeeMarketEIP1559Values.call(void 0, gasValues) && gasValues.maxPriorityFeePerGas;
++ const newMaxPriorityFeePerGas = maxPriorityFeePerGasValues && _chunkOZ6UB42Cjs.validateMinimumIncrease.call(void 0,
++ maxPriorityFeePerGasValues,
++ minMaxPriorityFeePerGas
++ ) || existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas;
++ const newTxParams = newMaxFeePerGas && newMaxPriorityFeePerGas ? {
++ from: transactionMeta.txParams.from,
++ gasLimit: transactionMeta.txParams.gas,
++ maxFeePerGas: newMaxFeePerGas,
++ maxPriorityFeePerGas: newMaxPriorityFeePerGas,
++ type: "0x2" /* feeMarket */,
++ nonce: transactionMeta.txParams.nonce,
++ to: transactionMeta.txParams.from,
++ value: "0x0"
++ } : {
++ from: transactionMeta.txParams.from,
++ gasLimit: transactionMeta.txParams.gas,
++ gasPrice: newGasPrice,
++ nonce: transactionMeta.txParams.nonce,
++ to: transactionMeta.txParams.from,
++ value: "0x0"
++ };
++ const unsignedEthTx = this.prepareUnsignedEthTx(
++ transactionMeta.chainId,
++ newTxParams
++ );
++ const signedTx = await this.sign(
++ unsignedEthTx,
++ transactionMeta.txParams.from
++ );
++ const rawTx = _util.bufferToHex.call(void 0, signedTx.serialize());
++ const newFee = newTxParams.maxFeePerGas ?? newTxParams.gasPrice;
++ const oldFee = newTxParams.maxFeePerGas ? transactionMeta.txParams.maxFeePerGas : transactionMeta.txParams.gasPrice;
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Submitting cancel transaction", {
++ oldFee,
++ newFee,
++ txParams: newTxParams
++ });
++ const ethQuery = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getEthQuery({
++ networkClientId: transactionMeta.networkClientId,
++ chainId: transactionMeta.chainId
++ });
++ const hash = await this.publishTransactionForRetry(
++ ethQuery,
++ rawTx,
++ transactionMeta
++ );
++ const cancelTransactionMeta = {
++ actionId,
++ chainId: transactionMeta.chainId,
++ networkClientId: transactionMeta.networkClientId,
++ estimatedBaseFee,
++ hash,
++ id: _uuid.v1.call(void 0, ),
++ originalGasEstimate: transactionMeta.txParams.gas,
++ rawTx,
++ status: "submitted" /* submitted */,
++ time: Date.now(),
++ type: "cancel" /* cancel */,
++ txParams: newTxParams
++ };
++ this.addMetadata(cancelTransactionMeta);
++ this.messagingSystem.publish(`${controllerName}:transactionApproved`, {
++ transactionMeta: cancelTransactionMeta,
++ actionId
++ });
++ this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {
++ transactionMeta: cancelTransactionMeta,
++ actionId
++ });
++ this.messagingSystem.publish(
++ `${controllerName}:transactionFinished`,
++ cancelTransactionMeta
++ );
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _internalEvents).emit(
++ `${transactionMeta.id}:finished`,
++ cancelTransactionMeta
++ );
++ }
++ /**
++ * Attempts to speed up a transaction increasing transaction gasPrice by ten percent.
++ *
++ * @param transactionId - The ID of the transaction to speed up.
++ * @param gasValues - The gas values to use for the speed up transaction.
++ * @param options - The options for the speed up transaction.
++ * @param options.actionId - Unique ID to prevent duplicate requests
++ * @param options.estimatedBaseFee - The estimated base fee of the transaction.
++ */
++ async speedUpTransaction(transactionId, gasValues, {
++ actionId,
++ estimatedBaseFee
++ } = {}) {
++ if (this.getTransactionWithActionId(actionId)) {
++ return;
++ }
++ if (gasValues) {
++ gasValues = _chunkOZ6UB42Cjs.normalizeGasFeeValues.call(void 0, gasValues);
++ _chunkOZ6UB42Cjs.validateGasValues.call(void 0, gasValues);
++ }
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Creating speed up transaction", transactionId, gasValues);
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ return;
++ }
++ if (!this.sign) {
++ throw new Error("No sign method defined.");
++ }
++ const minGasPrice = _chunkOZ6UB42Cjs.getIncreasedPriceFromExisting.call(void 0,
++ transactionMeta.txParams.gasPrice,
++ SPEED_UP_RATE
++ );
++ const gasPriceFromValues = _chunkOZ6UB42Cjs.isGasPriceValue.call(void 0, gasValues) && gasValues.gasPrice;
++ const newGasPrice = gasPriceFromValues && _chunkOZ6UB42Cjs.validateMinimumIncrease.call(void 0, gasPriceFromValues, minGasPrice) || minGasPrice;
++ const existingMaxFeePerGas = transactionMeta.txParams?.maxFeePerGas;
++ const minMaxFeePerGas = _chunkOZ6UB42Cjs.getIncreasedPriceFromExisting.call(void 0,
++ existingMaxFeePerGas,
++ SPEED_UP_RATE
++ );
++ const maxFeePerGasValues = _chunkOZ6UB42Cjs.isFeeMarketEIP1559Values.call(void 0, gasValues) && gasValues.maxFeePerGas;
++ const newMaxFeePerGas = maxFeePerGasValues && _chunkOZ6UB42Cjs.validateMinimumIncrease.call(void 0, maxFeePerGasValues, minMaxFeePerGas) || existingMaxFeePerGas && minMaxFeePerGas;
++ const existingMaxPriorityFeePerGas = transactionMeta.txParams?.maxPriorityFeePerGas;
++ const minMaxPriorityFeePerGas = _chunkOZ6UB42Cjs.getIncreasedPriceFromExisting.call(void 0,
++ existingMaxPriorityFeePerGas,
++ SPEED_UP_RATE
++ );
++ const maxPriorityFeePerGasValues = _chunkOZ6UB42Cjs.isFeeMarketEIP1559Values.call(void 0, gasValues) && gasValues.maxPriorityFeePerGas;
++ const newMaxPriorityFeePerGas = maxPriorityFeePerGasValues && _chunkOZ6UB42Cjs.validateMinimumIncrease.call(void 0,
++ maxPriorityFeePerGasValues,
++ minMaxPriorityFeePerGas
++ ) || existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas;
++ const txParams = newMaxFeePerGas && newMaxPriorityFeePerGas ? {
++ ...transactionMeta.txParams,
++ gasLimit: transactionMeta.txParams.gas,
++ maxFeePerGas: newMaxFeePerGas,
++ maxPriorityFeePerGas: newMaxPriorityFeePerGas,
++ type: "0x2" /* feeMarket */
++ } : {
++ ...transactionMeta.txParams,
++ gasLimit: transactionMeta.txParams.gas,
++ gasPrice: newGasPrice
++ };
++ const unsignedEthTx = this.prepareUnsignedEthTx(
++ transactionMeta.chainId,
++ txParams
++ );
++ const signedTx = await this.sign(
++ unsignedEthTx,
++ transactionMeta.txParams.from
++ );
++ const transactionMetaWithRsv = this.updateTransactionMetaRSV(
++ transactionMeta,
++ signedTx
++ );
++ const rawTx = _util.bufferToHex.call(void 0, signedTx.serialize());
++ const newFee = txParams.maxFeePerGas ?? txParams.gasPrice;
++ const oldFee = txParams.maxFeePerGas ? transactionMetaWithRsv.txParams.maxFeePerGas : transactionMetaWithRsv.txParams.gasPrice;
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Submitting speed up transaction", { oldFee, newFee, txParams });
++ const ethQuery = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getEthQuery({
++ networkClientId: transactionMeta.networkClientId,
++ chainId: transactionMeta.chainId
++ });
++ const hash = await this.publishTransactionForRetry(
++ ethQuery,
++ rawTx,
++ transactionMeta
++ );
++ const baseTransactionMeta = {
++ ...transactionMetaWithRsv,
++ estimatedBaseFee,
++ id: _uuid.v1.call(void 0, ),
++ time: Date.now(),
++ hash,
++ actionId,
++ originalGasEstimate: transactionMeta.txParams.gas,
++ type: "retry" /* retry */,
++ originalType: transactionMeta.type
++ };
++ const newTransactionMeta = newMaxFeePerGas && newMaxPriorityFeePerGas ? {
++ ...baseTransactionMeta,
++ txParams: {
++ ...transactionMeta.txParams,
++ maxFeePerGas: newMaxFeePerGas,
++ maxPriorityFeePerGas: newMaxPriorityFeePerGas
++ }
++ } : {
++ ...baseTransactionMeta,
++ txParams: {
++ ...transactionMeta.txParams,
++ gasPrice: newGasPrice
++ }
++ };
++ this.addMetadata(newTransactionMeta);
++ this.messagingSystem.publish(`${controllerName}:transactionApproved`, {
++ transactionMeta: newTransactionMeta,
++ actionId
++ });
++ this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {
++ transactionMeta: newTransactionMeta,
++ actionId
++ });
++ this.messagingSystem.publish(
++ `${controllerName}:speedupTransactionAdded`,
++ newTransactionMeta
++ );
++ }
++ /**
++ * Estimates required gas for a given transaction.
++ *
++ * @param transaction - The transaction to estimate gas for.
++ * @param networkClientId - The network client id to use for the estimate.
++ * @returns The gas and gas price.
++ */
++ async estimateGas(transaction, networkClientId) {
++ const ethQuery = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getEthQuery({
++ networkClientId
++ });
++ const { estimatedGas, simulationFails } = await _chunkV72C4MCRjs.estimateGas.call(void 0,
++ transaction,
++ ethQuery
++ );
++ return { gas: estimatedGas, simulationFails };
++ }
++ /**
++ * Estimates required gas for a given transaction and add additional gas buffer with the given multiplier.
++ *
++ * @param transaction - The transaction params to estimate gas for.
++ * @param multiplier - The multiplier to use for the gas buffer.
++ * @param networkClientId - The network client id to use for the estimate.
++ */
++ async estimateGasBuffered(transaction, multiplier, networkClientId) {
++ const ethQuery = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getEthQuery({
++ networkClientId
++ });
++ const { blockGasLimit, estimatedGas, simulationFails } = await _chunkV72C4MCRjs.estimateGas.call(void 0,
++ transaction,
++ ethQuery
++ );
++ const gas = _chunkV72C4MCRjs.addGasBuffer.call(void 0, estimatedGas, blockGasLimit, multiplier);
++ return {
++ gas,
++ simulationFails
++ };
++ }
++ /**
++ * Updates an existing transaction in state.
++ *
++ * @param transactionMeta - The new transaction to store in state.
++ * @param note - A note or update reason to include in the transaction history.
++ */
++ updateTransaction(transactionMeta, note) {
++ const { id: transactionId } = transactionMeta;
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, { transactionId, note }, () => ({
++ ...transactionMeta
++ }));
++ }
++ /**
++ * Update the security alert response for a transaction.
++ *
++ * @param transactionId - ID of the transaction.
++ * @param securityAlertResponse - The new security alert response for the transaction.
++ */
++ updateSecurityAlertResponse(transactionId, securityAlertResponse) {
++ if (!securityAlertResponse) {
++ throw new Error(
++ "updateSecurityAlertResponse: securityAlertResponse should not be null"
++ );
++ }
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ throw new Error(
++ `Cannot update security alert response as no transaction metadata found`
++ );
++ }
++ const updatedTransactionMeta = {
++ ...transactionMeta,
++ securityAlertResponse
++ };
++ this.updateTransaction(
++ updatedTransactionMeta,
++ `${controllerName}:updatesecurityAlertResponse - securityAlertResponse updated`
++ );
++ }
++ /**
++ * Removes all transactions from state, optionally based on the current network.
++ *
++ * @param ignoreNetwork - Determines whether to wipe all transactions, or just those on the
++ * current network. If `true`, all transactions are wiped.
++ * @param address - If specified, only transactions originating from this address will be
++ * wiped on current network.
++ */
++ wipeTransactions(ignoreNetwork, address) {
++ if (ignoreNetwork && !address) {
++ this.update((state) => {
++ state.transactions = [];
++ });
++ return;
++ }
++ const currentChainId = this.getChainId();
++ const newTransactions = this.state.transactions.filter(
++ ({ chainId, txParams }) => {
++ const isMatchingNetwork = ignoreNetwork || chainId === currentChainId;
++ if (!isMatchingNetwork) {
++ return true;
++ }
++ const isMatchingAddress = !address || txParams.from?.toLowerCase() === address.toLowerCase();
++ return !isMatchingAddress;
++ }
++ );
++ this.update((state) => {
++ state.transactions = this.trimTransactionsForState(newTransactions);
++ });
++ }
++ /**
++ * Adds external provided transaction to state as confirmed transaction.
++ *
++ * @param transactionMeta - TransactionMeta to add transactions.
++ * @param transactionReceipt - TransactionReceipt of the external transaction.
++ * @param baseFeePerGas - Base fee per gas of the external transaction.
++ */
++ async confirmExternalTransaction(transactionMeta, transactionReceipt, baseFeePerGas) {
++ const newTransactionMeta = this.addExternalTransaction(transactionMeta);
++ try {
++ const transactionId = newTransactionMeta.id;
++ const updatedTransactionMeta = {
++ ...newTransactionMeta,
++ status: "confirmed" /* confirmed */,
++ txReceipt: transactionReceipt
++ };
++ if (baseFeePerGas) {
++ updatedTransactionMeta.baseFeePerGas = baseFeePerGas;
++ }
++ this.markNonceDuplicatesDropped(transactionId);
++ this.updateTransaction(
++ updatedTransactionMeta,
++ `${controllerName}:confirmExternalTransaction - Add external transaction`
++ );
++ this.onTransactionStatusChange(updatedTransactionMeta);
++ this.updatePostBalance(updatedTransactionMeta);
++ this.messagingSystem.publish(
++ `${controllerName}:transactionConfirmed`,
++ updatedTransactionMeta
++ );
++ } catch (error) {
++ console.error("Failed to confirm external transaction", error);
++ }
++ }
++ /**
++ * Append new send flow history to a transaction.
++ *
++ * @param transactionID - The ID of the transaction to update.
++ * @param currentSendFlowHistoryLength - The length of the current sendFlowHistory array.
++ * @param sendFlowHistoryToAdd - The sendFlowHistory entries to add.
++ * @returns The updated transactionMeta.
++ */
++ updateTransactionSendFlowHistory(transactionID, currentSendFlowHistoryLength, sendFlowHistoryToAdd) {
++ if (this.isSendFlowHistoryDisabled) {
++ throw new Error(
++ "Send flow history is disabled for the current transaction controller"
++ );
++ }
++ const transactionMeta = this.getTransaction(transactionID);
++ if (!transactionMeta) {
++ throw new Error(
++ `Cannot update send flow history as no transaction metadata found`
++ );
++ }
++ _chunkOZ6UB42Cjs.validateIfTransactionUnapproved.call(void 0,
++ transactionMeta,
++ "updateTransactionSendFlowHistory"
++ );
++ const sendFlowHistory = transactionMeta.sendFlowHistory ?? [];
++ if (currentSendFlowHistoryLength === sendFlowHistory.length) {
++ const updatedTransactionMeta = {
++ ...transactionMeta,
++ sendFlowHistory: [...sendFlowHistory, ...sendFlowHistoryToAdd]
++ };
++ this.updateTransaction(
++ updatedTransactionMeta,
++ `${controllerName}:updateTransactionSendFlowHistory - sendFlowHistory updated`
++ );
++ }
++ return this.getTransaction(transactionID);
++ }
++ /**
++ * Update the gas values of a transaction.
++ *
++ * @param transactionId - The ID of the transaction to update.
++ * @param gasValues - Gas values to update.
++ * @param gasValues.gas - Same as transaction.gasLimit.
++ * @param gasValues.gasLimit - Maxmimum number of units of gas to use for this transaction.
++ * @param gasValues.gasPrice - Price per gas for legacy transactions.
++ * @param gasValues.maxPriorityFeePerGas - Maximum amount per gas to give to validator as incentive.
++ * @param gasValues.maxFeePerGas - Maximum amount per gas to pay for the transaction, including the priority fee.
++ * @param gasValues.estimateUsed - Which estimate level was used.
++ * @param gasValues.estimateSuggested - Which estimate level that the API suggested.
++ * @param gasValues.defaultGasEstimates - The default estimate for gas.
++ * @param gasValues.originalGasEstimate - Original estimate for gas.
++ * @param gasValues.userEditedGasLimit - The gas limit supplied by user.
++ * @param gasValues.userFeeLevel - Estimate level user selected.
++ * @returns The updated transactionMeta.
++ */
++ updateTransactionGasFees(transactionId, {
++ defaultGasEstimates,
++ estimateUsed,
++ estimateSuggested,
++ gas,
++ gasLimit,
++ gasPrice,
++ maxPriorityFeePerGas,
++ maxFeePerGas,
++ originalGasEstimate,
++ userEditedGasLimit,
++ userFeeLevel
++ }) {
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ throw new Error(
++ `Cannot update transaction as no transaction metadata found`
++ );
++ }
++ _chunkOZ6UB42Cjs.validateIfTransactionUnapproved.call(void 0,
++ transactionMeta,
++ "updateTransactionGasFees"
++ );
++ let transactionGasFees = {
++ txParams: {
++ gas,
++ gasLimit,
++ gasPrice,
++ maxPriorityFeePerGas,
++ maxFeePerGas
++ },
++ defaultGasEstimates,
++ estimateUsed,
++ estimateSuggested,
++ originalGasEstimate,
++ userEditedGasLimit,
++ userFeeLevel
++ // TODO: Replace `any` with type
++ // eslint-disable-next-line @typescript-eslint/no-explicit-any
++ };
++ transactionGasFees.txParams = _lodash.pickBy.call(void 0, transactionGasFees.txParams);
++ transactionGasFees = _lodash.pickBy.call(void 0, transactionGasFees);
++ const updatedMeta = _lodash.merge.call(void 0, {}, transactionMeta, transactionGasFees);
++ this.updateTransaction(
++ updatedMeta,
++ `${controllerName}:updateTransactionGasFees - gas values updated`
++ );
++ return this.getTransaction(transactionId);
++ }
++ /**
++ * Update the previous gas values of a transaction.
++ *
++ * @param transactionId - The ID of the transaction to update.
++ * @param previousGas - Previous gas values to update.
++ * @param previousGas.gasLimit - Maxmimum number of units of gas to use for this transaction.
++ * @param previousGas.maxFeePerGas - Maximum amount per gas to pay for the transaction, including the priority fee.
++ * @param previousGas.maxPriorityFeePerGas - Maximum amount per gas to give to validator as incentive.
++ * @returns The updated transactionMeta.
++ */
++ updatePreviousGasParams(transactionId, {
++ gasLimit,
++ maxFeePerGas,
++ maxPriorityFeePerGas
++ }) {
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ throw new Error(
++ `Cannot update transaction as no transaction metadata found`
++ );
++ }
++ _chunkOZ6UB42Cjs.validateIfTransactionUnapproved.call(void 0, transactionMeta, "updatePreviousGasParams");
++ const transactionPreviousGas = {
++ previousGas: {
++ gasLimit,
++ maxFeePerGas,
++ maxPriorityFeePerGas
++ }
++ // TODO: Replace `any` with type
++ // eslint-disable-next-line @typescript-eslint/no-explicit-any
++ };
++ transactionPreviousGas.previousGas = _lodash.pickBy.call(void 0,
++ transactionPreviousGas.previousGas
++ );
++ const updatedMeta = _lodash.merge.call(void 0, {}, transactionMeta, transactionPreviousGas);
++ this.updateTransaction(
++ updatedMeta,
++ `${controllerName}:updatePreviousGasParams - Previous gas values updated`
++ );
++ return this.getTransaction(transactionId);
++ }
++ async getNonceLock(address, networkClientId) {
++ return _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getNonceLock(
++ address,
++ networkClientId
++ );
++ }
++ /**
++ * Updates the editable parameters of a transaction.
++ *
++ * @param txId - The ID of the transaction to update.
++ * @param params - The editable parameters to update.
++ * @param params.data - Data to pass with the transaction.
++ * @param params.gas - Maximum number of units of gas to use for the transaction.
++ * @param params.gasPrice - Price per gas for legacy transactions.
++ * @param params.from - Address to send the transaction from.
++ * @param params.to - Address to send the transaction to.
++ * @param params.value - Value associated with the transaction.
++ * @returns The updated transaction metadata.
++ */
++ async updateEditableParams(txId, {
++ data,
++ gas,
++ gasPrice,
++ from,
++ to,
++ value
++ }) {
++ const transactionMeta = this.getTransaction(txId);
++ if (!transactionMeta) {
++ throw new Error(
++ `Cannot update editable params as no transaction metadata found`
++ );
++ }
++ _chunkOZ6UB42Cjs.validateIfTransactionUnapproved.call(void 0, transactionMeta, "updateEditableParams");
++ const editableParams = {
++ txParams: {
++ data,
++ from,
++ to,
++ value,
++ gas,
++ gasPrice
++ }
++ };
++ editableParams.txParams = _lodash.pickBy.call(void 0,
++ editableParams.txParams
++ );
++ const updatedTransaction = _lodash.merge.call(void 0, {}, transactionMeta, editableParams);
++ const provider = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getProvider({
++ chainId: transactionMeta.chainId,
++ networkClientId: transactionMeta.networkClientId
++ });
++ const ethQuery = new (0, _ethquery2.default)(provider);
++ const { type } = await _chunkSD6CWFDFjs.determineTransactionType.call(void 0,
++ updatedTransaction.txParams,
++ ethQuery
++ );
++ updatedTransaction.type = type;
++ await _chunk2XKEAKQGjs.updateTransactionLayer1GasFee.call(void 0, {
++ layer1GasFeeFlows: this.layer1GasFeeFlows,
++ provider,
++ transactionMeta: updatedTransaction
++ });
++ this.updateTransaction(
++ updatedTransaction,
++ `Update Editable Params for ${txId}`
++ );
++ return this.getTransaction(txId);
++ }
++ /**
++ * Signs and returns the raw transaction data for provided transaction params list.
++ *
++ * @param listOfTxParams - The list of transaction params to approve.
++ * @param opts - Options bag.
++ * @param opts.hasNonce - Whether the transactions already have a nonce.
++ * @returns The raw transactions.
++ */
++ async approveTransactionsWithSameNonce(listOfTxParams = [], { hasNonce } = {}) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Approving transactions with same nonce", {
++ transactions: listOfTxParams
++ });
++ if (listOfTxParams.length === 0) {
++ return "";
++ }
++ const initialTx = listOfTxParams[0];
++ const common = this.getCommonConfiguration(initialTx.chainId);
++ let networkClientId;
++ try {
++ networkClientId = this.messagingSystem.call(
++ `NetworkController:findNetworkClientIdByChainId`,
++ initialTx.chainId
++ );
++ } catch (err) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "failed to find networkClientId from chainId", err);
++ }
++ const initialTxAsEthTx = _tx.TransactionFactory.fromTxData(initialTx, {
++ common
++ });
++ const initialTxAsSerializedHex = _util.bufferToHex.call(void 0, initialTxAsEthTx.serialize());
++ if (this.approvingTransactionIds.has(initialTxAsSerializedHex)) {
++ return "";
++ }
++ this.approvingTransactionIds.add(initialTxAsSerializedHex);
++ let rawTransactions, nonceLock;
++ try {
++ const fromAddress = initialTx.from;
++ const requiresNonce = hasNonce !== true;
++ nonceLock = requiresNonce ? await this.getNonceLock(fromAddress, networkClientId) : void 0;
++ const nonce = nonceLock ? _utils.add0x.call(void 0, nonceLock.nextNonce.toString(16)) : initialTx.nonce;
++ if (nonceLock) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Using nonce from nonce tracker", nonce, nonceLock.nonceDetails);
++ }
++ rawTransactions = await Promise.all(
++ listOfTxParams.map((txParams) => {
++ txParams.nonce = nonce;
++ return this.signExternalTransaction(txParams.chainId, txParams);
++ })
++ );
++ } catch (err) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Error while signing transactions with same nonce", err);
++ throw err;
++ } finally {
++ nonceLock?.releaseLock();
++ this.approvingTransactionIds.delete(initialTxAsSerializedHex);
++ }
++ return rawTransactions;
++ }
++ /**
++ * Update a custodial transaction.
++ *
++ * @param transactionId - The ID of the transaction to update.
++ * @param options - The custodial transaction options to update.
++ * @param options.errorMessage - The error message to be assigned in case transaction status update to failed.
++ * @param options.hash - The new hash value to be assigned.
++ * @param options.status - The new status value to be assigned.
++ */
++ updateCustodialTransaction(transactionId, {
++ errorMessage,
++ hash,
++ status
++ }) {
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ throw new Error(
++ `Cannot update custodial transaction as no transaction metadata found`
++ );
++ }
++ if (!transactionMeta.custodyId) {
++ throw new Error("Transaction must be a custodian transaction");
++ }
++ if (status && ![
++ "submitted" /* submitted */,
++ "signed" /* signed */,
++ "failed" /* failed */
++ ].includes(status)) {
++ throw new Error(
++ `Cannot update custodial transaction with status: ${status}`
++ );
++ }
++ const updatedTransactionMeta = _lodash.merge.call(void 0,
++ {},
++ transactionMeta,
++ _lodash.pickBy.call(void 0, { hash, status })
++ );
++ if (updatedTransactionMeta.status === "submitted" /* submitted */) {
++ updatedTransactionMeta.submittedTime = (/* @__PURE__ */ new Date()).getTime();
++ }
++ if (updatedTransactionMeta.status === "failed" /* failed */) {
++ updatedTransactionMeta.error = _chunkOZ6UB42Cjs.normalizeTxError.call(void 0, new Error(errorMessage));
++ }
++ this.updateTransaction(
++ updatedTransactionMeta,
++ `${controllerName}:updateCustodialTransaction - Custodial transaction updated`
++ );
++ if (["submitted" /* submitted */, "failed" /* failed */].includes(
++ status
++ )) {
++ this.messagingSystem.publish(
++ `${controllerName}:transactionFinished`,
++ updatedTransactionMeta
++ );
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _internalEvents).emit(
++ `${updatedTransactionMeta.id}:finished`,
++ updatedTransactionMeta
++ );
++ }
++ }
++ /**
++ * Search transaction metadata for matching entries.
++ *
++ * @param opts - Options bag.
++ * @param opts.searchCriteria - An object containing values or functions for transaction properties to filter transactions with.
++ * @param opts.initialList - The transactions to search. Defaults to the current state.
++ * @param opts.filterToCurrentNetwork - Whether to filter the results to the current network. Defaults to true.
++ * @param opts.limit - The maximum number of transactions to return. No limit by default.
++ * @returns An array of transactions matching the provided options.
++ */
++ getTransactions({
++ searchCriteria = {},
++ initialList,
++ filterToCurrentNetwork = true,
++ limit
++ } = {}) {
++ const chainId = this.getChainId();
++ const predicateMethods = _lodash.mapValues.call(void 0, searchCriteria, (predicate) => {
++ return typeof predicate === "function" ? predicate : (
++ // TODO: Replace `any` with type
++ // eslint-disable-next-line @typescript-eslint/no-explicit-any
++ (v) => v === predicate
++ );
++ });
++ const transactionsToFilter = initialList ?? this.state.transactions;
++ const filteredTransactions = _lodash.sortBy.call(void 0,
++ _lodash.pickBy.call(void 0, transactionsToFilter, (transaction) => {
++ if (filterToCurrentNetwork && transaction.chainId !== chainId) {
++ return false;
++ }
++ for (const [key, predicate] of Object.entries(predicateMethods)) {
++ if (key in transaction.txParams) {
++ if (predicate(transaction.txParams[key]) === false) {
++ return false;
++ }
++ } else if (predicate(transaction[key]) === false) {
++ return false;
++ }
++ }
++ return true;
++ }),
++ "time"
++ );
++ if (limit !== void 0) {
++ const nonces = /* @__PURE__ */ new Set();
++ const txs = [];
++ for (let i = filteredTransactions.length - 1; i > -1; i--) {
++ const txMeta = filteredTransactions[i];
++ const { nonce } = txMeta.txParams;
++ if (!nonces.has(nonce)) {
++ if (nonces.size < limit) {
++ nonces.add(nonce);
++ } else {
++ continue;
++ }
++ }
++ txs.unshift(txMeta);
++ }
++ return txs;
++ }
++ return filteredTransactions;
++ }
++ async estimateGasFee({
++ transactionParams,
++ chainId,
++ networkClientId: requestNetworkClientId
++ }) {
++ const networkClientId = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getNetworkClientId, getNetworkClientId_fn).call(this, {
++ networkClientId: requestNetworkClientId,
++ chainId
++ });
++ const transactionMeta = {
++ txParams: transactionParams,
++ chainId,
++ networkClientId
++ };
++ const gasFeeFlow = _chunk76FONEDAjs.getGasFeeFlow.call(void 0,
++ transactionMeta,
++ this.gasFeeFlows
++ );
++ const ethQuery = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getEthQuery({
++ networkClientId,
++ chainId
++ });
++ const gasFeeControllerData = await this.getGasFeeEstimates({
++ networkClientId
++ });
++ return gasFeeFlow.getGasFees({
++ ethQuery,
++ gasFeeControllerData,
++ transactionMeta
++ });
++ }
++ /**
++ * Determine the layer 1 gas fee for the given transaction parameters.
++ *
++ * @param request - The request object.
++ * @param request.transactionParams - The transaction parameters to estimate the layer 1 gas fee for.
++ * @param request.chainId - The ID of the chain where the transaction will be executed.
++ * @param request.networkClientId - The ID of a specific network client to process the transaction.
++ */
++ async getLayer1GasFee({
++ transactionParams,
++ chainId,
++ networkClientId
++ }) {
++ const provider = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getProvider({
++ networkClientId,
++ chainId
++ });
++ return await _chunk2XKEAKQGjs.getTransactionLayer1GasFee.call(void 0, {
++ layer1GasFeeFlows: this.layer1GasFeeFlows,
++ provider,
++ transactionMeta: {
++ txParams: transactionParams,
++ chainId
++ }
++ });
++ }
++ async signExternalTransaction(chainId, transactionParams) {
++ if (!this.sign) {
++ throw new Error("No sign method defined.");
++ }
++ const normalizedTransactionParams = _chunkOZ6UB42Cjs.normalizeTransactionParams.call(void 0, transactionParams);
++ const type = _chunkOZ6UB42Cjs.isEIP1559Transaction.call(void 0, normalizedTransactionParams) ? "0x2" /* feeMarket */ : "0x0" /* legacy */;
++ const updatedTransactionParams = {
++ ...normalizedTransactionParams,
++ type,
++ gasLimit: normalizedTransactionParams.gas,
++ chainId
++ };
++ const { from } = updatedTransactionParams;
++ const common = this.getCommonConfiguration(chainId);
++ const unsignedTransaction = _tx.TransactionFactory.fromTxData(
++ updatedTransactionParams,
++ { common }
++ );
++ const signedTransaction = await this.sign(unsignedTransaction, from);
++ const rawTransaction = _util.bufferToHex.call(void 0, signedTransaction.serialize());
++ return rawTransaction;
++ }
++ /**
++ * Removes unapproved transactions from state.
++ */
++ clearUnapprovedTransactions() {
++ const transactions = this.state.transactions.filter(
++ ({ status }) => status !== "unapproved" /* unapproved */
++ );
++ this.update((state) => {
++ state.transactions = this.trimTransactionsForState(transactions);
++ });
++ }
++ /**
++ * Stop the signing process for a specific transaction.
++ * Throws an error causing the transaction status to be set to failed.
++ * @param transactionId - The ID of the transaction to stop signing.
++ */
++ abortTransactionSigning(transactionId) {
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ throw new Error(`Cannot abort signing as no transaction metadata found`);
++ }
++ const abortCallback = this.signAbortCallbacks.get(transactionId);
++ if (!abortCallback) {
++ throw new Error(
++ `Cannot abort signing as transaction is not waiting for signing`
++ );
++ }
++ abortCallback();
++ this.signAbortCallbacks.delete(transactionId);
++ }
++ addMetadata(transactionMeta) {
++ this.update((state) => {
++ state.transactions = this.trimTransactionsForState([
++ ...state.transactions,
++ transactionMeta
++ ]);
++ });
++ }
++ async updateGasProperties(transactionMeta) {
++ const isEIP1559Compatible = await this.getEIP1559Compatibility(transactionMeta.networkClientId) && transactionMeta.txParams.type !== "0x0" /* legacy */;
++ const { networkClientId, chainId } = transactionMeta;
++ const isCustomNetwork = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _isCustomNetwork, isCustomNetwork_fn).call(this, networkClientId);
++ const ethQuery = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getEthQuery({
++ networkClientId,
++ chainId
++ });
++ const provider = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getProvider({
++ networkClientId,
++ chainId
++ });
++ await _chunkV72C4MCRjs.updateGas.call(void 0, {
++ ethQuery,
++ chainId,
++ isCustomNetwork,
++ txMeta: transactionMeta
++ });
++ await _chunkC3WC4OJ3js.updateGasFees.call(void 0, {
++ eip1559: isEIP1559Compatible,
++ ethQuery,
++ gasFeeFlows: this.gasFeeFlows,
++ getGasFeeEstimates: this.getGasFeeEstimates,
++ getSavedGasFees: this.getSavedGasFees.bind(this),
++ txMeta: transactionMeta
++ });
++ await _chunk2XKEAKQGjs.updateTransactionLayer1GasFee.call(void 0, {
++ layer1GasFeeFlows: this.layer1GasFeeFlows,
++ provider,
++ transactionMeta
++ });
++ }
++ onBootCleanup() {
++ this.clearUnapprovedTransactions();
++ this.failIncompleteTransactions();
++ }
++ failIncompleteTransactions() {
++ const incompleteTransactions = this.state.transactions.filter(
++ (transaction) => ["approved" /* approved */, "signed" /* signed */].includes(
++ transaction.status
++ )
++ );
++ for (const transactionMeta of incompleteTransactions) {
++ this.failTransaction(
++ transactionMeta,
++ new Error("Transaction incomplete at startup")
++ );
++ }
++ }
++ async processApproval(transactionMeta, {
++ isExisting = false,
++ requireApproval,
++ shouldShowRequest = true,
++ actionId
++ }) {
++ const transactionId = transactionMeta.id;
++ let resultCallbacks;
++ const { meta, isCompleted } = this.isTransactionCompleted(transactionId);
++ const finishedPromise = isCompleted ? Promise.resolve(meta) : this.waitForTransactionFinished(transactionId);
++ if (meta && !isExisting && !isCompleted) {
++ try {
++ if (requireApproval !== false) {
++ const acceptResult = await this.requestApproval(transactionMeta, {
++ shouldShowRequest
++ });
++ resultCallbacks = acceptResult.resultCallbacks;
++ const approvalValue = acceptResult.value;
++ const updatedTransaction = approvalValue?.txMeta;
++ if (updatedTransaction) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Updating transaction with approval data", {
++ customNonce: updatedTransaction.customNonceValue,
++ params: updatedTransaction.txParams
++ });
++ this.updateTransaction(
++ updatedTransaction,
++ "TransactionController#processApproval - Updated with approval data"
++ );
++ }
++ }
++ const { isCompleted: isTxCompleted } = this.isTransactionCompleted(transactionId);
++ if (!isTxCompleted) {
++ const approvalResult = await this.approveTransaction(transactionId);
++ if (approvalResult === "skipped-via-before-publish-hook" /* SkippedViaBeforePublishHook */ && resultCallbacks) {
++ resultCallbacks.success();
++ }
++ const updatedTransactionMeta = this.getTransaction(
++ transactionId
++ );
++ this.messagingSystem.publish(
++ `${controllerName}:transactionApproved`,
++ {
++ transactionMeta: updatedTransactionMeta,
++ actionId
++ }
++ );
++ }
++ } catch (error) {
++ const { isCompleted: isTxCompleted } = this.isTransactionCompleted(transactionId);
++ if (!isTxCompleted) {
++ if (error?.code === _rpcerrors.errorCodes.provider.userRejectedRequest) {
++ this.cancelTransaction(transactionId, actionId);
++ throw _rpcerrors.providerErrors.userRejectedRequest(
++ "MetaMask Tx Signature: User denied transaction signature."
++ );
++ } else {
++ this.failTransaction(meta, error, actionId);
++ }
++ }
++ }
++ }
++ const finalMeta = await finishedPromise;
++ switch (finalMeta?.status) {
++ case "failed" /* failed */:
++ resultCallbacks?.error(finalMeta.error);
++ throw _rpcerrors.rpcErrors.internal(finalMeta.error.message);
++ case "submitted" /* submitted */:
++ resultCallbacks?.success();
++ return finalMeta.hash;
++ default:
++ const internalError = _rpcerrors.rpcErrors.internal(
++ `MetaMask Tx Signature: Unknown problem: ${JSON.stringify(
++ finalMeta || transactionId
++ )}`
++ );
++ resultCallbacks?.error(internalError);
++ throw internalError;
++ }
++ }
++ /**
++ * Approves a transaction and updates it's status in state. If this is not a
++ * retry transaction, a nonce will be generated. The transaction is signed
++ * using the sign configuration property, then published to the blockchain.
++ * A `:finished` hub event is fired after success or failure.
++ *
++ * @param transactionId - The ID of the transaction to approve.
++ */
++ async approveTransaction(transactionId) {
++ const cleanupTasks = new Array();
++ cleanupTasks.push(await this.mutex.acquire());
++ let transactionMeta = this.getTransactionOrThrow(transactionId);
++ try {
++ if (!this.sign) {
++ this.failTransaction(
++ transactionMeta,
++ new Error("No sign method defined.")
++ );
++ return "not-approved" /* NotApproved */;
++ } else if (!transactionMeta.chainId) {
++ this.failTransaction(transactionMeta, new Error("No chainId defined."));
++ return "not-approved" /* NotApproved */;
++ }
++ if (this.approvingTransactionIds.has(transactionId)) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Skipping approval as signing in progress", transactionId);
++ return "not-approved" /* NotApproved */;
++ }
++ this.approvingTransactionIds.add(transactionId);
++ cleanupTasks.push(
++ () => this.approvingTransactionIds.delete(transactionId)
++ );
++ const [nonce, releaseNonce] = await _chunkPRUNMTRDjs.getNextNonce.call(void 0,
++ transactionMeta,
++ (address) => _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getNonceLock(
++ address,
++ transactionMeta.networkClientId
++ )
++ );
++ releaseNonce && cleanupTasks.push(releaseNonce);
++ transactionMeta = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, {
++ transactionId,
++ note: "TransactionController#approveTransaction - Transaction approved"
++ }, (draftTxMeta) => {
++ const { txParams, chainId } = draftTxMeta;
++ draftTxMeta.status = "approved" /* approved */;
++ draftTxMeta.txParams = {
++ ...txParams,
++ nonce,
++ chainId,
++ gasLimit: txParams.gas,
++ ..._chunkOZ6UB42Cjs.isEIP1559Transaction.call(void 0, txParams) && {
++ type: "0x2" /* feeMarket */
++ }
++ };
++ });
++ this.onTransactionStatusChange(transactionMeta);
++ const rawTx = await this.signTransaction(
++ transactionMeta,
++ transactionMeta.txParams
++ );
++ if (!this.beforePublish(transactionMeta)) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Skipping publishing transaction based on hook");
++ this.messagingSystem.publish(
++ `${controllerName}:transactionPublishingSkipped`,
++ transactionMeta
++ );
++ return "skipped-via-before-publish-hook" /* SkippedViaBeforePublishHook */;
++ }
++ if (!rawTx) {
++ return "not-approved" /* NotApproved */;
++ }
++ const ethQuery = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getEthQuery({
++ networkClientId: transactionMeta.networkClientId,
++ chainId: transactionMeta.chainId
++ });
++ let preTxBalance;
++ const shouldUpdatePreTxBalance = transactionMeta.type === "swap" /* swap */;
++ if (shouldUpdatePreTxBalance) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Determining pre-transaction balance");
++ preTxBalance = await _controllerutils.query.call(void 0, ethQuery, "getBalance", [
++ transactionMeta.txParams.from
++ ]);
++ }
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Publishing transaction", transactionMeta.txParams);
++ let { transactionHash: hash } = await this.publish(
++ transactionMeta,
++ rawTx
++ );
++ if (hash === void 0) {
++ hash = await this.publishTransaction(ethQuery, rawTx);
++ }
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Publish successful", hash);
++ transactionMeta = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, {
++ transactionId,
++ note: "TransactionController#approveTransaction - Transaction submitted"
++ }, (draftTxMeta) => {
++ draftTxMeta.hash = hash;
++ draftTxMeta.status = "submitted" /* submitted */;
++ draftTxMeta.submittedTime = (/* @__PURE__ */ new Date()).getTime();
++ if (shouldUpdatePreTxBalance) {
++ draftTxMeta.preTxBalance = preTxBalance;
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Updated pre-transaction balance", preTxBalance);
++ }
++ });
++ this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {
++ transactionMeta
++ });
++ this.messagingSystem.publish(
++ `${controllerName}:transactionFinished`,
++ transactionMeta
++ );
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _internalEvents).emit(`${transactionId}:finished`, transactionMeta);
++ this.onTransactionStatusChange(transactionMeta);
++ return "approved" /* Approved */;
++ } catch (error) {
++ this.failTransaction(transactionMeta, error);
++ return "not-approved" /* NotApproved */;
++ } finally {
++ cleanupTasks.forEach((task) => task());
++ }
++ }
++ async publishTransaction(ethQuery, rawTransaction) {
++ return await _controllerutils.query.call(void 0, ethQuery, "sendRawTransaction", [rawTransaction]);
++ }
++ /**
++ * Cancels a transaction based on its ID by setting its status to "rejected"
++ * and emitting a `:finished` hub event.
++ *
++ * @param transactionId - The ID of the transaction to cancel.
++ * @param actionId - The actionId passed from UI
++ */
++ cancelTransaction(transactionId, actionId) {
++ const transactionMeta = this.state.transactions.find(
++ ({ id }) => id === transactionId
++ );
++ if (!transactionMeta) {
++ return;
++ }
++ this.update((state) => {
++ const transactions = state.transactions.filter(
++ ({ id }) => id !== transactionId
++ );
++ state.transactions = this.trimTransactionsForState(transactions);
++ });
++ const updatedTransactionMeta = {
++ ...transactionMeta,
++ status: "rejected" /* rejected */
++ };
++ this.messagingSystem.publish(
++ `${controllerName}:transactionFinished`,
++ updatedTransactionMeta
++ );
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _internalEvents).emit(
++ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
++ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
++ `${transactionMeta.id}:finished`,
++ updatedTransactionMeta
++ );
++ this.messagingSystem.publish(`${controllerName}:transactionRejected`, {
++ transactionMeta: updatedTransactionMeta,
++ actionId
++ });
++ this.onTransactionStatusChange(updatedTransactionMeta);
++ }
++ /**
++ * Trim the amount of transactions that are set on the state. Checks
++ * if the length of the tx history is longer then desired persistence
++ * limit and then if it is removes the oldest confirmed or rejected tx.
++ * Pending or unapproved transactions will not be removed by this
++ * operation. For safety of presenting a fully functional transaction UI
++ * representation, this function will not break apart transactions with the
++ * same nonce, created on the same day, per network. Not accounting for
++ * transactions of the same nonce, same day and network combo can result in
++ * confusing or broken experiences in the UI.
++ *
++ * @param transactions - The transactions to be applied to the state.
++ * @returns The trimmed list of transactions.
++ */
++ trimTransactionsForState(transactions) {
++ const nonceNetworkSet = /* @__PURE__ */ new Set();
++ const txsToKeep = [...transactions].sort((a, b) => a.time > b.time ? -1 : 1).filter((tx) => {
++ const { chainId, status, txParams, time } = tx;
++ if (txParams) {
++ const key = `${String(txParams.nonce)}-${_controllerutils.convertHexToDecimal.call(void 0,
++ chainId
++ )}-${new Date(time).toDateString()}`;
++ if (nonceNetworkSet.has(key)) {
++ return true;
++ } else if (nonceNetworkSet.size < _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _transactionHistoryLimit) || !this.isFinalState(status)) {
++ nonceNetworkSet.add(key);
++ return true;
++ }
++ }
++ return false;
++ });
++ txsToKeep.reverse();
++ return txsToKeep;
++ }
++ /**
++ * Determines if the transaction is in a final state.
++ *
++ * @param status - The transaction status.
++ * @returns Whether the transaction is in a final state.
++ */
++ isFinalState(status) {
++ return status === "rejected" /* rejected */ || status === "confirmed" /* confirmed */ || status === "failed" /* failed */;
++ }
++ /**
++ * Whether the transaction has at least completed all local processing.
++ *
++ * @param status - The transaction status.
++ * @returns Whether the transaction is in a final state.
++ */
++ isLocalFinalState(status) {
++ return [
++ "confirmed" /* confirmed */,
++ "failed" /* failed */,
++ "rejected" /* rejected */,
++ "submitted" /* submitted */
++ ].includes(status);
++ }
++ async requestApproval(txMeta, { shouldShowRequest }) {
++ const id = this.getApprovalId(txMeta);
++ const { origin } = txMeta;
++ const type = _controllerutils.ApprovalType.Transaction;
++ const requestData = { txId: txMeta.id };
++ return await this.messagingSystem.call(
++ "ApprovalController:addRequest",
++ {
++ id,
++ origin: origin || _controllerutils.ORIGIN_METAMASK,
++ type,
++ requestData,
++ expectsResult: true
++ },
++ shouldShowRequest
++ );
++ }
++ getTransaction(transactionId) {
++ const { transactions } = this.state;
++ return transactions.find(({ id }) => id === transactionId);
++ }
++ getTransactionOrThrow(transactionId, errorMessagePrefix = "TransactionController") {
++ const txMeta = this.getTransaction(transactionId);
++ if (!txMeta) {
++ throw new Error(
++ `${errorMessagePrefix}: No transaction found with id ${transactionId}`
++ );
++ }
++ return txMeta;
++ }
++ getApprovalId(txMeta) {
++ return String(txMeta.id);
++ }
++ isTransactionCompleted(transactionId) {
++ const transaction = this.getTransaction(transactionId);
++ if (!transaction) {
++ return { meta: void 0, isCompleted: false };
++ }
++ const isCompleted = this.isLocalFinalState(transaction.status);
++ return { meta: transaction, isCompleted };
++ }
++ getChainId(networkClientId) {
++ const globalChainId = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getGlobalChainId, getGlobalChainId_fn).call(this);
++ const globalNetworkClientId = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getGlobalNetworkClientId, getGlobalNetworkClientId_fn).call(this);
++ if (!networkClientId || networkClientId === globalNetworkClientId) {
++ return globalChainId;
++ }
++ return this.messagingSystem.call(
++ `NetworkController:getNetworkClientById`,
++ networkClientId
++ ).configuration.chainId;
++ }
++ prepareUnsignedEthTx(chainId, txParams) {
++ return _tx.TransactionFactory.fromTxData(txParams, {
++ freeze: false,
++ common: this.getCommonConfiguration(chainId)
++ });
++ }
++ /**
++ * `@ethereumjs/tx` uses `@ethereumjs/common` as a configuration tool for
++ * specifying which chain, network, hardfork and EIPs to support for
++ * a transaction. By referencing this configuration, and analyzing the fields
++ * specified in txParams, @ethereumjs/tx is able to determine which EIP-2718
++ * transaction type to use.
++ *
++ * @param chainId - The chainId to use for the configuration.
++ * @returns common configuration object
++ */
++ getCommonConfiguration(chainId) {
++ const customChainParams = {
++ chainId: parseInt(chainId, 16),
++ defaultHardfork: HARDFORK
++ };
++ return _common.Common.custom(customChainParams);
++ }
++ onIncomingTransactions({
++ added,
++ updated
++ }) {
++ this.update((state) => {
++ const { transactions: currentTransactions } = state;
++ const updatedTransactions = [
++ ...added,
++ ...currentTransactions.map((originalTransaction) => {
++ const updatedTransaction = updated.find(
++ ({ hash }) => hash === originalTransaction.hash
++ );
++ return updatedTransaction ?? originalTransaction;
++ })
++ ];
++ state.transactions = this.trimTransactionsForState(updatedTransactions);
++ });
++ }
++ onUpdatedLastFetchedBlockNumbers({
++ lastFetchedBlockNumbers,
++ blockNumber
++ }) {
++ this.update((state) => {
++ state.lastFetchedBlockNumbers = lastFetchedBlockNumbers;
++ });
++ this.messagingSystem.publish(
++ `${controllerName}:incomingTransactionBlockReceived`,
++ blockNumber
++ );
++ }
++ generateDappSuggestedGasFees(txParams, origin) {
++ if (!origin || origin === _controllerutils.ORIGIN_METAMASK) {
++ return void 0;
++ }
++ const { gasPrice, maxFeePerGas, maxPriorityFeePerGas, gas } = txParams;
++ if (gasPrice === void 0 && maxFeePerGas === void 0 && maxPriorityFeePerGas === void 0 && gas === void 0) {
++ return void 0;
++ }
++ const dappSuggestedGasFees = {};
++ if (gasPrice !== void 0) {
++ dappSuggestedGasFees.gasPrice = gasPrice;
++ } else if (maxFeePerGas !== void 0 || maxPriorityFeePerGas !== void 0) {
++ dappSuggestedGasFees.maxFeePerGas = maxFeePerGas;
++ dappSuggestedGasFees.maxPriorityFeePerGas = maxPriorityFeePerGas;
++ }
++ if (gas !== void 0) {
++ dappSuggestedGasFees.gas = gas;
++ }
++ return dappSuggestedGasFees;
++ }
++ /**
++ * Validates and adds external provided transaction to state.
++ *
++ * @param transactionMeta - Nominated external transaction to be added to state.
++ * @returns The new transaction.
++ */
++ addExternalTransaction(transactionMeta) {
++ const { chainId } = transactionMeta;
++ const { transactions } = this.state;
++ const fromAddress = transactionMeta?.txParams?.from;
++ const sameFromAndNetworkTransactions = transactions.filter(
++ (transaction) => transaction.txParams.from === fromAddress && transaction.chainId === chainId
++ );
++ const confirmedTxs = sameFromAndNetworkTransactions.filter(
++ (transaction) => transaction.status === "confirmed" /* confirmed */
++ );
++ const pendingTxs = sameFromAndNetworkTransactions.filter(
++ (transaction) => transaction.status === "submitted" /* submitted */
++ );
++ _chunk7LXE4KHVjs.validateConfirmedExternalTransaction.call(void 0,
++ transactionMeta,
++ confirmedTxs,
++ pendingTxs
++ );
++ const newTransactionMeta = (transactionMeta.history ?? []).length === 0 && !this.isHistoryDisabled ? _chunkQP75SWIQjs.addInitialHistorySnapshot.call(void 0, transactionMeta) : transactionMeta;
++ this.update((state) => {
++ state.transactions = this.trimTransactionsForState([
++ ...state.transactions,
++ newTransactionMeta
++ ]);
++ });
++ return newTransactionMeta;
++ }
++ /**
++ * Sets other txMeta statuses to dropped if the txMeta that has been confirmed has other transactions
++ * in the transactions have the same nonce.
++ *
++ * @param transactionId - Used to identify original transaction.
++ */
++ markNonceDuplicatesDropped(transactionId) {
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ return;
++ }
++ const nonce = transactionMeta.txParams?.nonce;
++ const from = transactionMeta.txParams?.from;
++ const { chainId } = transactionMeta;
++ const sameNonceTransactions = this.state.transactions.filter(
++ (transaction) => transaction.id !== transactionId && transaction.txParams.from === from && transaction.txParams.nonce === nonce && transaction.chainId === chainId && transaction.type !== "incoming" /* incoming */
++ );
++ const sameNonceTransactionIds = sameNonceTransactions.map(
++ (transaction) => transaction.id
++ );
++ if (sameNonceTransactions.length === 0) {
++ return;
++ }
++ this.update((state) => {
++ for (const transaction of state.transactions) {
++ if (sameNonceTransactionIds.includes(transaction.id)) {
++ transaction.replacedBy = transactionMeta?.hash;
++ transaction.replacedById = transactionMeta?.id;
++ }
++ }
++ });
++ for (const transaction of this.state.transactions) {
++ if (sameNonceTransactionIds.includes(transaction.id) && transaction.status !== "failed" /* failed */) {
++ this.setTransactionStatusDropped(transaction);
++ }
++ }
++ }
++ /**
++ * Method to set transaction status to dropped.
++ *
++ * @param transactionMeta - TransactionMeta of transaction to be marked as dropped.
++ */
++ setTransactionStatusDropped(transactionMeta) {
++ const updatedTransactionMeta = {
++ ...transactionMeta,
++ status: "dropped" /* dropped */
++ };
++ this.messagingSystem.publish(`${controllerName}:transactionDropped`, {
++ transactionMeta: updatedTransactionMeta
++ });
++ this.updateTransaction(
++ updatedTransactionMeta,
++ "TransactionController#setTransactionStatusDropped - Transaction dropped"
++ );
++ this.onTransactionStatusChange(updatedTransactionMeta);
++ }
++ /**
++ * Get transaction with provided actionId.
++ *
++ * @param actionId - Unique ID to prevent duplicate requests
++ * @returns the filtered transaction
++ */
++ getTransactionWithActionId(actionId) {
++ return this.state.transactions.find(
++ (transaction) => actionId && transaction.actionId === actionId
++ );
++ }
++ async waitForTransactionFinished(transactionId) {
++ return new Promise((resolve) => {
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _internalEvents).once(`${transactionId}:finished`, (txMeta) => {
++ resolve(txMeta);
++ });
++ });
++ }
++ /**
++ * Updates the r, s, and v properties of a TransactionMeta object
++ * with values from a signed transaction.
++ *
++ * @param transactionMeta - The TransactionMeta object to update.
++ * @param signedTx - The encompassing type for all transaction types containing r, s, and v values.
++ * @returns The updated TransactionMeta object.
++ */
++ updateTransactionMetaRSV(transactionMeta, signedTx) {
++ const transactionMetaWithRsv = _lodash.cloneDeep.call(void 0, transactionMeta);
++ for (const key of ["r", "s", "v"]) {
++ const value = signedTx[key];
++ if (value === void 0 || value === null) {
++ continue;
++ }
++ transactionMetaWithRsv[key] = _utils.add0x.call(void 0, value.toString(16));
++ }
++ return transactionMetaWithRsv;
++ }
++ async getEIP1559Compatibility(networkClientId) {
++ const currentNetworkIsEIP1559Compatible = await this.getCurrentNetworkEIP1559Compatibility(networkClientId);
++ const currentAccountIsEIP1559Compatible = await this.getCurrentAccountEIP1559Compatibility();
++ return currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible;
++ }
++ async signTransaction(transactionMeta, txParams) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Signing transaction", txParams);
++ const unsignedEthTx = this.prepareUnsignedEthTx(
++ transactionMeta.chainId,
++ txParams
++ );
++ this.approvingTransactionIds.add(transactionMeta.id);
++ const signedTx = await new Promise((resolve, reject) => {
++ this.sign?.(
++ unsignedEthTx,
++ txParams.from,
++ ...this.getAdditionalSignArguments(transactionMeta)
++ ).then(resolve, reject);
++ this.signAbortCallbacks.set(
++ transactionMeta.id,
++ () => reject(new Error("Signing aborted by user"))
++ );
++ });
++ this.signAbortCallbacks.delete(transactionMeta.id);
++ if (!signedTx) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Skipping signed status as no signed transaction");
++ return void 0;
++ }
++ const transactionMetaFromHook = _lodash.cloneDeep.call(void 0, transactionMeta);
++ if (!this.afterSign(transactionMetaFromHook, signedTx)) {
++ this.updateTransaction(
++ transactionMetaFromHook,
++ "TransactionController#signTransaction - Update after sign"
++ );
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Skipping signed status based on hook");
++ return void 0;
++ }
++ const transactionMetaWithRsv = {
++ ...this.updateTransactionMetaRSV(transactionMetaFromHook, signedTx),
++ status: "signed" /* signed */
++ };
++ this.updateTransaction(
++ transactionMetaWithRsv,
++ "TransactionController#approveTransaction - Transaction signed"
++ );
++ this.onTransactionStatusChange(transactionMetaWithRsv);
++ const rawTx = _util.bufferToHex.call(void 0, signedTx.serialize());
++ const transactionMetaWithRawTx = _lodash.merge.call(void 0, {}, transactionMetaWithRsv, {
++ rawTx
++ });
++ this.updateTransaction(
++ transactionMetaWithRawTx,
++ "TransactionController#approveTransaction - RawTransaction added"
++ );
++ return rawTx;
++ }
++ onTransactionStatusChange(transactionMeta) {
++ this.messagingSystem.publish(`${controllerName}:transactionStatusUpdated`, {
++ transactionMeta
++ });
++ }
++ getNonceTrackerTransactions(status, address, chainId = this.getChainId()) {
++ return _chunkPRUNMTRDjs.getAndFormatTransactionsForNonceTracker.call(void 0,
++ chainId,
++ address,
++ status,
++ this.state.transactions
++ );
++ }
++ onConfirmedTransaction(transactionMeta) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Processing confirmed transaction", transactionMeta.id);
++ this.markNonceDuplicatesDropped(transactionMeta.id);
++ this.messagingSystem.publish(
++ `${controllerName}:transactionConfirmed`,
++ transactionMeta
++ );
++ this.onTransactionStatusChange(transactionMeta);
++ this.updatePostBalance(transactionMeta);
++ }
++ async updatePostBalance(transactionMeta) {
++ try {
++ if (transactionMeta.type !== "swap" /* swap */) {
++ return;
++ }
++ const ethQuery = _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).getEthQuery({
++ networkClientId: transactionMeta.networkClientId,
++ chainId: transactionMeta.chainId
++ });
++ const { updatedTransactionMeta, approvalTransactionMeta } = await _chunkQH2H4W3Njs.updatePostTransactionBalance.call(void 0, transactionMeta, {
++ ethQuery,
++ getTransaction: this.getTransaction.bind(this),
++ updateTransaction: this.updateTransaction.bind(this)
++ });
++ this.messagingSystem.publish(
++ `${controllerName}:postTransactionBalanceUpdated`,
++ {
++ transactionMeta: updatedTransactionMeta,
++ approvalTransactionMeta
++ }
++ );
++ } catch (error) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Error while updating post transaction balance", error);
++ }
++ }
++ async publishTransactionForRetry(ethQuery, rawTx, transactionMeta) {
++ try {
++ const hash = await this.publishTransaction(ethQuery, rawTx);
++ return hash;
++ } catch (error) {
++ if (this.isTransactionAlreadyConfirmedError(error)) {
++ await this.pendingTransactionTracker.forceCheckTransaction(
++ transactionMeta
++ );
++ throw new Error("Previous transaction is already confirmed");
++ }
++ throw error;
++ }
++ }
++ /**
++ * Ensures that error is a nonce issue
++ *
++ * @param error - The error to check
++ * @returns Whether or not the error is a nonce issue
++ */
++ // TODO: Replace `any` with type
++ // Some networks are returning original error in the data field
++ // eslint-disable-next-line @typescript-eslint/no-explicit-any
++ isTransactionAlreadyConfirmedError(error) {
++ return error?.message?.includes("nonce too low") || error?.data?.message?.includes("nonce too low");
++ }
++};
++_internalEvents = new WeakMap();
++_incomingTransactionOptions = new WeakMap();
++_pendingTransactionOptions = new WeakMap();
++_transactionHistoryLimit = new WeakMap();
++_isSimulationEnabled = new WeakMap();
++_testGasFeeFlows = new WeakMap();
++_multichainTrackingHelper = new WeakMap();
++_createNonceTracker = new WeakSet();
++createNonceTracker_fn = function({
++ provider,
++ blockTracker,
++ chainId
++}) {
++ return new (0, _noncetracker.NonceTracker)({
++ // TODO: Fix types
++ // eslint-disable-next-line @typescript-eslint/no-explicit-any
++ provider,
++ // @ts-expect-error TODO: Fix types
++ blockTracker,
++ getPendingTransactions: _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getNonceTrackerPendingTransactions, getNonceTrackerPendingTransactions_fn).bind(
++ this,
++ chainId
++ ),
++ getConfirmedTransactions: this.getNonceTrackerTransactions.bind(
++ this,
++ "confirmed" /* confirmed */
++ )
++ });
++};
++_createIncomingTransactionHelper = new WeakSet();
++createIncomingTransactionHelper_fn = function({
++ blockTracker,
++ etherscanRemoteTransactionSource,
++ chainId
++}) {
++ const incomingTransactionHelper = new (0, _chunkRHDPOIS4js.IncomingTransactionHelper)({
++ blockTracker,
++ getCurrentAccount: () => _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getSelectedAccount, getSelectedAccount_fn).call(this),
++ getLastFetchedBlockNumbers: () => this.state.lastFetchedBlockNumbers,
++ getChainId: chainId ? () => chainId : this.getChainId.bind(this),
++ isEnabled: _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _incomingTransactionOptions).isEnabled,
++ queryEntireHistory: _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _incomingTransactionOptions).queryEntireHistory,
++ remoteTransactionSource: etherscanRemoteTransactionSource,
++ transactionLimit: _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _transactionHistoryLimit),
++ updateTransactions: _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _incomingTransactionOptions).updateTransactions
++ });
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _addIncomingTransactionHelperListeners, addIncomingTransactionHelperListeners_fn).call(this, incomingTransactionHelper);
++ return incomingTransactionHelper;
++};
++_createPendingTransactionTracker = new WeakSet();
++createPendingTransactionTracker_fn = function({
++ provider,
++ blockTracker,
++ chainId
++}) {
++ const ethQuery = new (0, _ethquery2.default)(provider);
++ const getChainId = chainId ? () => chainId : this.getChainId.bind(this);
++ const pendingTransactionTracker = new (0, _chunk6DODV6OVjs.PendingTransactionTracker)({
++ blockTracker,
++ getChainId,
++ getEthQuery: () => ethQuery,
++ getTransactions: () => this.state.transactions,
++ isResubmitEnabled: _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _pendingTransactionOptions).isResubmitEnabled,
++ getGlobalLock: () => _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).acquireNonceLockForChainIdKey({
++ chainId: getChainId()
++ }),
++ publishTransaction: this.publishTransaction.bind(this),
++ hooks: {
++ beforeCheckPendingTransaction: this.beforeCheckPendingTransaction.bind(this),
++ beforePublish: this.beforePublish.bind(this)
++ }
++ });
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _addPendingTransactionTrackerListeners, addPendingTransactionTrackerListeners_fn).call(this, pendingTransactionTracker);
++ return pendingTransactionTracker;
++};
++_checkForPendingTransactionAndStartPolling = new WeakMap();
++_stopAllTracking = new WeakSet();
++stopAllTracking_fn = function() {
++ this.pendingTransactionTracker.stop();
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _removePendingTransactionTrackerListeners, removePendingTransactionTrackerListeners_fn).call(this, this.pendingTransactionTracker);
++ this.incomingTransactionHelper.stop();
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _removeIncomingTransactionHelperListeners, removeIncomingTransactionHelperListeners_fn).call(this, this.incomingTransactionHelper);
++ _chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _multichainTrackingHelper).stopAllTracking();
++};
++_removeIncomingTransactionHelperListeners = new WeakSet();
++removeIncomingTransactionHelperListeners_fn = function(incomingTransactionHelper) {
++ incomingTransactionHelper.hub.removeAllListeners("transactions");
++ incomingTransactionHelper.hub.removeAllListeners(
++ "updatedLastFetchedBlockNumbers"
++ );
++};
++_addIncomingTransactionHelperListeners = new WeakSet();
++addIncomingTransactionHelperListeners_fn = function(incomingTransactionHelper) {
++ incomingTransactionHelper.hub.on(
++ "transactions",
++ this.onIncomingTransactions.bind(this)
++ );
++ incomingTransactionHelper.hub.on(
++ "updatedLastFetchedBlockNumbers",
++ this.onUpdatedLastFetchedBlockNumbers.bind(this)
++ );
++};
++_removePendingTransactionTrackerListeners = new WeakSet();
++removePendingTransactionTrackerListeners_fn = function(pendingTransactionTracker) {
++ pendingTransactionTracker.hub.removeAllListeners("transaction-confirmed");
++ pendingTransactionTracker.hub.removeAllListeners("transaction-dropped");
++ pendingTransactionTracker.hub.removeAllListeners("transaction-failed");
++ pendingTransactionTracker.hub.removeAllListeners("transaction-updated");
++};
++_addPendingTransactionTrackerListeners = new WeakSet();
++addPendingTransactionTrackerListeners_fn = function(pendingTransactionTracker) {
++ pendingTransactionTracker.hub.on(
++ "transaction-confirmed",
++ this.onConfirmedTransaction.bind(this)
++ );
++ pendingTransactionTracker.hub.on(
++ "transaction-dropped",
++ this.setTransactionStatusDropped.bind(this)
++ );
++ pendingTransactionTracker.hub.on(
++ "transaction-failed",
++ this.failTransaction.bind(this)
++ );
++ pendingTransactionTracker.hub.on(
++ "transaction-updated",
++ this.updateTransaction.bind(this)
++ );
++};
++_getNonceTrackerPendingTransactions = new WeakSet();
++getNonceTrackerPendingTransactions_fn = function(chainId, address) {
++ const standardPendingTransactions = this.getNonceTrackerTransactions(
++ "submitted" /* submitted */,
++ address,
++ chainId
++ );
++ const externalPendingTransactions = this.getExternalPendingTransactions(
++ address,
++ chainId
++ );
++ return [...standardPendingTransactions, ...externalPendingTransactions];
++};
++_getGasFeeFlows = new WeakSet();
++getGasFeeFlows_fn = function() {
++ if (_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _testGasFeeFlows)) {
++ return [new (0, _chunkTJMQEH57js.TestGasFeeFlow)()];
++ }
++ return [new (0, _chunkARZHJFVGjs.LineaGasFeeFlow)(), new (0, _chunkQTKXIDGEjs.DefaultGasFeeFlow)()];
++};
++_getLayer1GasFeeFlows = new WeakSet();
++getLayer1GasFeeFlows_fn = function() {
++ return [new (0, _chunkNYKRCWBGjs.OptimismLayer1GasFeeFlow)(), new (0, _chunkWR5F34OWjs.ScrollLayer1GasFeeFlow)()];
++};
++_updateTransactionInternal = new WeakSet();
++updateTransactionInternal_fn = function({
++ transactionId,
++ note,
++ skipHistory,
++ skipValidation
++}, callback) {
++ let updatedTransactionParams = [];
++ this.update((state) => {
++ const index = state.transactions.findIndex(
++ ({ id }) => id === transactionId
++ );
++ let transactionMeta2 = state.transactions[index];
++ transactionMeta2 = callback(transactionMeta2) ?? transactionMeta2;
++ if (skipValidation !== true) {
++ transactionMeta2.txParams = _chunkOZ6UB42Cjs.normalizeTransactionParams.call(void 0,
++ transactionMeta2.txParams
++ );
++ _chunkRXIUMVA5js.validateTxParams.call(void 0, transactionMeta2.txParams);
++ }
++ updatedTransactionParams = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _checkIfTransactionParamsUpdated, checkIfTransactionParamsUpdated_fn).call(this, transactionMeta2);
++ const shouldSkipHistory = this.isHistoryDisabled || skipHistory;
++ if (!shouldSkipHistory) {
++ transactionMeta2 = _chunkQP75SWIQjs.updateTransactionHistory.call(void 0,
++ transactionMeta2,
++ note ?? "Transaction updated"
++ );
++ }
++ state.transactions[index] = transactionMeta2;
++ });
++ const transactionMeta = this.getTransaction(
++ transactionId
++ );
++ if (updatedTransactionParams.length > 0) {
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _onTransactionParamsUpdated, onTransactionParamsUpdated_fn).call(this, transactionMeta, updatedTransactionParams);
++ }
++ return transactionMeta;
++};
++_checkIfTransactionParamsUpdated = new WeakSet();
++checkIfTransactionParamsUpdated_fn = function(newTransactionMeta) {
++ const { id: transactionId, txParams: newParams } = newTransactionMeta;
++ const originalParams = this.getTransaction(transactionId)?.txParams;
++ if (!originalParams || _lodash.isEqual.call(void 0, originalParams, newParams)) {
++ return [];
++ }
++ const params = Object.keys(newParams);
++ const updatedProperties = params.filter(
++ (param) => newParams[param] !== originalParams[param]
++ );
++ _chunkS6VGOPUYjs.projectLogger.call(void 0,
++ "Transaction parameters have been updated",
++ transactionId,
++ updatedProperties,
++ originalParams,
++ newParams
++ );
++ return updatedProperties;
++};
++_onTransactionParamsUpdated = new WeakSet();
++onTransactionParamsUpdated_fn = function(transactionMeta, updatedParams) {
++ if (["to", "value", "data"].some(
++ (param) => updatedParams.includes(param)
++ )) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Updating simulation data due to transaction parameter update");
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateSimulationData, updateSimulationData_fn).call(this, transactionMeta);
++ }
++};
++_updateSimulationData = new WeakSet();
++updateSimulationData_fn = async function(transactionMeta) {
++ const { id: transactionId, chainId, txParams } = transactionMeta;
++ const { from, to, value, data } = txParams;
++ let simulationData = {
++ error: {
++ code: "disabled" /* Disabled */,
++ message: "Simulation disabled"
++ },
++ tokenBalanceChanges: []
++ };
++ if (_chunkZ4BLTVTBjs.__privateGet.call(void 0, this, _isSimulationEnabled).call(this)) {
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, { transactionId, skipHistory: true }, (txMeta) => {
++ txMeta.simulationData = void 0;
++ });
++ simulationData = await _chunk74W7X6BEjs.getSimulationData.call(void 0, {
++ chainId,
++ from,
++ to,
++ value,
++ data
++ });
++ }
++ const finalTransactionMeta = this.getTransaction(transactionId);
++ if (!finalTransactionMeta) {
++ _chunkS6VGOPUYjs.projectLogger.call(void 0,
++ "Cannot update simulation data as transaction not found",
++ transactionId,
++ simulationData
++ );
++ return;
++ }
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, {
++ transactionId,
++ note: "TransactionController#updateSimulationData - Update simulation data"
++ }, (txMeta) => {
++ txMeta.simulationData = simulationData;
++ });
++ _chunkS6VGOPUYjs.projectLogger.call(void 0, "Updated simulation data", transactionId, simulationData);
++};
++_onGasFeePollerTransactionUpdate = new WeakSet();
++onGasFeePollerTransactionUpdate_fn = function({
++ transactionId,
++ gasFeeEstimates,
++ gasFeeEstimatesLoaded,
++ layer1GasFee
++}) {
++ _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, { transactionId, skipHistory: true }, (txMeta) => {
++ if (gasFeeEstimates) {
++ txMeta.gasFeeEstimates = gasFeeEstimates;
++ }
++ if (gasFeeEstimatesLoaded !== void 0) {
++ txMeta.gasFeeEstimatesLoaded = gasFeeEstimatesLoaded;
++ }
++ if (layer1GasFee) {
++ txMeta.layer1GasFee = layer1GasFee;
++ }
++ });
++};
++_getNetworkClientId = new WeakSet();
++getNetworkClientId_fn = function({
++ networkClientId: requestNetworkClientId,
++ chainId
++}) {
++ const globalChainId = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getGlobalChainId, getGlobalChainId_fn).call(this);
++ const globalNetworkClientId = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getGlobalNetworkClientId, getGlobalNetworkClientId_fn).call(this);
++ if (requestNetworkClientId) {
++ return requestNetworkClientId;
++ }
++ if (!chainId || chainId === globalChainId) {
++ return globalNetworkClientId;
++ }
++ return this.messagingSystem.call(
++ `NetworkController:findNetworkClientIdByChainId`,
++ chainId
++ );
++};
++_getGlobalNetworkClientId = new WeakSet();
++getGlobalNetworkClientId_fn = function() {
++ return this.getNetworkState().selectedNetworkClientId;
++};
++_getGlobalChainId = new WeakSet();
++getGlobalChainId_fn = function() {
++ return this.messagingSystem.call(
++ `NetworkController:getNetworkClientById`,
++ this.getNetworkState().selectedNetworkClientId
++ ).configuration.chainId;
++};
++_isCustomNetwork = new WeakSet();
++isCustomNetwork_fn = function(networkClientId) {
++ const globalNetworkClientId = _chunkZ4BLTVTBjs.__privateMethod.call(void 0, this, _getGlobalNetworkClientId, getGlobalNetworkClientId_fn).call(this);
++ if (!networkClientId || networkClientId === globalNetworkClientId) {
++ return !_controllerutils.isInfuraNetworkType.call(void 0,
++ this.getNetworkState().selectedNetworkClientId
++ );
++ }
++ return this.messagingSystem.call(
++ `NetworkController:getNetworkClientById`,
++ networkClientId
++ ).configuration.type === _networkcontroller.NetworkClientType.Custom;
++};
++_getSelectedAccount = new WeakSet();
++getSelectedAccount_fn = function() {
++ return this.messagingSystem.call("AccountsController:getSelectedAccount");
++};
++
++
++
++
++
++
++
++exports.HARDFORK = HARDFORK; exports.CANCEL_RATE = CANCEL_RATE; exports.SPEED_UP_RATE = SPEED_UP_RATE; exports.ApprovalState = ApprovalState; exports.TransactionController = TransactionController;
++//# sourceMappingURL=chunk-IVR4NMOF.js.map
+\ No newline at end of file
+diff --git a/dist/chunk-IVR4NMOF.js.map b/dist/chunk-IVR4NMOF.js.map
+new file mode 100644
+index 0000000000000000000000000000000000000000..e06df9082a1bf650bafaf9b2a3602a8c597cf6ed
+--- /dev/null
++++ b/dist/chunk-IVR4NMOF.js.map
+@@ -0,0 +1 @@
++{"version":3,"sources":["../src/TransactionController.ts"],"names":["ApprovalState","transactionMeta"],"mappings":"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","sourcesContent":["import { Hardfork, Common, type ChainConfig } from '@ethereumjs/common';\nimport type { TypedTransaction } from '@ethereumjs/tx';\nimport { TransactionFactory } from '@ethereumjs/tx';\nimport { bufferToHex } from '@ethereumjs/util';\nimport type { AccountsControllerGetSelectedAccountAction } from '@metamask/accounts-controller';\nimport type {\n AcceptResultCallbacks,\n AddApprovalRequest,\n AddResult,\n} from '@metamask/approval-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport {\n query,\n ApprovalType,\n ORIGIN_METAMASK,\n convertHexToDecimal,\n isInfuraNetworkType,\n} from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n FetchGasFeeEstimateOptions,\n GasFeeState,\n} from '@metamask/gas-fee-controller';\nimport type {\n BlockTracker,\n NetworkClientId,\n NetworkController,\n NetworkControllerStateChangeEvent,\n NetworkState,\n Provider,\n NetworkControllerFindNetworkClientIdByChainIdAction,\n NetworkControllerGetNetworkClientByIdAction,\n} from '@metamask/network-controller';\nimport { NetworkClientType } from '@metamask/network-controller';\nimport type {\n NonceLock,\n Transaction as NonceTrackerTransaction,\n} from '@metamask/nonce-tracker';\nimport { NonceTracker } from '@metamask/nonce-tracker';\nimport { errorCodes, rpcErrors, providerErrors } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\nimport { add0x } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { MethodRegistry } from 'eth-method-registry';\nimport { EventEmitter } from 'events';\nimport { cloneDeep, mapValues, merge, pickBy, sortBy, isEqual } from 'lodash';\nimport { v1 as random } from 'uuid';\n\nimport { DefaultGasFeeFlow } from './gas-flows/DefaultGasFeeFlow';\nimport { LineaGasFeeFlow } from './gas-flows/LineaGasFeeFlow';\nimport { OptimismLayer1GasFeeFlow } from './gas-flows/OptimismLayer1GasFeeFlow';\nimport { ScrollLayer1GasFeeFlow } from './gas-flows/ScrollLayer1GasFeeFlow';\nimport { TestGasFeeFlow } from './gas-flows/TestGasFeeFlow';\nimport { EtherscanRemoteTransactionSource } from './helpers/EtherscanRemoteTransactionSource';\nimport { GasFeePoller } from './helpers/GasFeePoller';\nimport type { IncomingTransactionOptions } from './helpers/IncomingTransactionHelper';\nimport { IncomingTransactionHelper } from './helpers/IncomingTransactionHelper';\nimport { MultichainTrackingHelper } from './helpers/MultichainTrackingHelper';\nimport { PendingTransactionTracker } from './helpers/PendingTransactionTracker';\nimport { projectLogger as log } from './logger';\nimport type {\n DappSuggestedGasFees,\n Layer1GasFeeFlow,\n SavedGasFees,\n SecurityProviderRequest,\n SendFlowHistoryEntry,\n TransactionParams,\n TransactionMeta,\n TransactionReceipt,\n WalletDevice,\n SecurityAlertResponse,\n GasFeeFlow,\n SimulationData,\n GasFeeEstimates,\n GasFeeFlowResponse,\n} from './types';\nimport {\n TransactionEnvelopeType,\n TransactionType,\n TransactionStatus,\n SimulationErrorCode,\n} from './types';\nimport { validateConfirmedExternalTransaction } from './utils/external-transactions';\nimport { addGasBuffer, estimateGas, updateGas } from './utils/gas';\nimport { updateGasFees } from './utils/gas-fees';\nimport { getGasFeeFlow } from './utils/gas-flow';\nimport {\n addInitialHistorySnapshot,\n updateTransactionHistory,\n} from './utils/history';\nimport {\n getTransactionLayer1GasFee,\n updateTransactionLayer1GasFee,\n} from './utils/layer1-gas-fee-flow';\nimport {\n getAndFormatTransactionsForNonceTracker,\n getNextNonce,\n} from './utils/nonce';\nimport { getSimulationData } from './utils/simulation';\nimport {\n updatePostTransactionBalance,\n updateSwapsTransaction,\n} from './utils/swaps';\nimport { determineTransactionType } from './utils/transaction-type';\nimport {\n getIncreasedPriceFromExisting,\n normalizeTransactionParams,\n isEIP1559Transaction,\n isFeeMarketEIP1559Values,\n isGasPriceValue,\n validateGasValues,\n validateIfTransactionUnapproved,\n validateMinimumIncrease,\n normalizeTxError,\n normalizeGasFeeValues,\n} from './utils/utils';\nimport {\n validateTransactionOrigin,\n validateTxParams,\n} from './utils/validation';\n\n/**\n * Metadata for the TransactionController state, describing how to \"anonymize\"\n * the state and which parts should be persisted.\n */\nconst metadata = {\n transactions: {\n persist: true,\n anonymous: false,\n },\n methodData: {\n persist: true,\n anonymous: false,\n },\n lastFetchedBlockNumbers: {\n persist: true,\n anonymous: false,\n },\n};\n\nexport const HARDFORK = Hardfork.London;\n\n/**\n * Object with new transaction's meta and a promise resolving to the\n * transaction hash if successful.\n *\n * @property result - Promise resolving to a new transaction hash\n * @property transactionMeta - Meta information about this new transaction\n */\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface Result {\n result: Promise;\n transactionMeta: TransactionMeta;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface GasPriceValue {\n gasPrice: string;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface FeeMarketEIP1559Values {\n maxFeePerGas: string;\n maxPriorityFeePerGas: string;\n}\n\n/**\n * Method data registry object\n *\n * @property registryMethod - Registry method raw string\n * @property parsedRegistryMethod - Registry method object, containing name and method arguments\n */\nexport type MethodData = {\n registryMethod: string;\n parsedRegistryMethod:\n | {\n name: string;\n args: { type: string }[];\n }\n | {\n // We're using `any` instead of `undefined` for compatibility with `Json`\n // TODO: Correct this type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n name?: any;\n // We're using `any` instead of `undefined` for compatibility with `Json`\n // TODO: Correct this type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n args?: any;\n };\n};\n\n/**\n * Transaction controller state\n *\n * @property transactions - A list of TransactionMeta objects\n * @property methodData - Object containing all known method data information\n * @property lastFetchedBlockNumbers - Last fetched block numbers.\n */\nexport type TransactionControllerState = {\n transactions: TransactionMeta[];\n methodData: Record;\n lastFetchedBlockNumbers: { [key: string]: number };\n};\n\n/**\n * Multiplier used to determine a transaction's increased gas fee during cancellation\n */\nexport const CANCEL_RATE = 1.1;\n\n/**\n * Multiplier used to determine a transaction's increased gas fee during speed up\n */\nexport const SPEED_UP_RATE = 1.1;\n\n/**\n * Represents the `TransactionController:getState` action.\n */\nexport type TransactionControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n TransactionControllerState\n>;\n\n/**\n * The internal actions available to the TransactionController.\n */\nexport type TransactionControllerActions = TransactionControllerGetStateAction;\n\n/**\n * Configuration options for the PendingTransactionTracker\n *\n * @property isResubmitEnabled - Whether transaction publishing is automatically retried.\n */\nexport type PendingTransactionOptions = {\n isResubmitEnabled?: () => boolean;\n};\n\n/**\n * TransactionController constructor options.\n *\n * @property blockTracker - The block tracker used to poll for new blocks data.\n * @property disableHistory - Whether to disable storing history in transaction metadata.\n * @property disableSendFlowHistory - Explicitly disable transaction metadata history.\n * @property disableSwaps - Whether to disable additional processing on swaps transactions.\n * @property getCurrentAccountEIP1559Compatibility - Whether or not the account supports EIP-1559.\n * @property getCurrentNetworkEIP1559Compatibility - Whether or not the network supports EIP-1559.\n * @property getExternalPendingTransactions - Callback to retrieve pending transactions from external sources.\n * @property getGasFeeEstimates - Callback to retrieve gas fee estimates.\n * @property getNetworkClientRegistry - Gets the network client registry.\n * @property getNetworkState - Gets the state of the network controller.\n * @property getPermittedAccounts - Get accounts that a given origin has permissions for.\n * @property getSavedGasFees - Gets the saved gas fee config.\n * @property getSelectedAddress - Gets the address of the currently selected account.\n * @property incomingTransactions - Configuration options for incoming transaction support.\n * @property isMultichainEnabled - Enable multichain support.\n * @property isSimulationEnabled - Whether new transactions will be automatically simulated.\n * @property messenger - The controller messenger.\n * @property onNetworkStateChange - Allows subscribing to network controller state changes.\n * @property pendingTransactions - Configuration options for pending transaction support.\n * @property provider - The provider used to create the underlying EthQuery instance.\n * @property securityProviderRequest - A function for verifying a transaction, whether it is malicious or not.\n * @property sign - Function used to sign transactions.\n * @property state - Initial state to set on this controller.\n * @property transactionHistoryLimit - Transaction history limit.\n * @property hooks - The controller hooks.\n * @property hooks.afterSign - Additional logic to execute after signing a transaction. Return false to not change the status to signed.\n * @property hooks.beforeCheckPendingTransaction - Additional logic to execute before checking pending transactions. Return false to prevent the broadcast of the transaction.\n * @property hooks.beforePublish - Additional logic to execute before publishing a transaction. Return false to prevent the broadcast of the transaction.\n * @property hooks.getAdditionalSignArguments - Returns additional arguments required to sign a transaction.\n * @property hooks.publish - Alternate logic to publish a transaction.\n */\nexport type TransactionControllerOptions = {\n blockTracker: BlockTracker;\n disableHistory: boolean;\n disableSendFlowHistory: boolean;\n disableSwaps: boolean;\n getCurrentAccountEIP1559Compatibility?: () => Promise;\n getCurrentNetworkEIP1559Compatibility: () => Promise;\n getExternalPendingTransactions?: (\n address: string,\n chainId?: string,\n ) => NonceTrackerTransaction[];\n getGasFeeEstimates?: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise;\n getNetworkClientRegistry: NetworkController['getNetworkClientRegistry'];\n getNetworkState: () => NetworkState;\n getPermittedAccounts: (origin?: string) => Promise;\n getSavedGasFees?: (chainId: Hex) => SavedGasFees | undefined;\n incomingTransactions?: IncomingTransactionOptions;\n isMultichainEnabled: boolean;\n isSimulationEnabled?: () => boolean;\n messenger: TransactionControllerMessenger;\n onNetworkStateChange: (listener: (state: NetworkState) => void) => void;\n pendingTransactions?: PendingTransactionOptions;\n provider: Provider;\n securityProviderRequest?: SecurityProviderRequest;\n sign?: (\n transaction: TypedTransaction,\n from: string,\n transactionMeta?: TransactionMeta,\n ) => Promise;\n state?: Partial;\n testGasFeeFlows?: boolean;\n transactionHistoryLimit: number;\n hooks: {\n afterSign?: (\n transactionMeta: TransactionMeta,\n signedTx: TypedTransaction,\n ) => boolean;\n beforeCheckPendingTransaction?: (\n transactionMeta: TransactionMeta,\n ) => boolean;\n beforePublish?: (transactionMeta: TransactionMeta) => boolean;\n getAdditionalSignArguments?: (\n transactionMeta: TransactionMeta,\n ) => (TransactionMeta | undefined)[];\n publish?: (\n transactionMeta: TransactionMeta,\n ) => Promise<{ transactionHash: string }>;\n };\n};\n\n/**\n * The name of the {@link TransactionController}.\n */\nconst controllerName = 'TransactionController';\n\n/**\n * The external actions available to the {@link TransactionController}.\n */\nexport type AllowedActions =\n | AddApprovalRequest\n | NetworkControllerFindNetworkClientIdByChainIdAction\n | NetworkControllerGetNetworkClientByIdAction\n | AccountsControllerGetSelectedAccountAction;\n\n/**\n * The external events available to the {@link TransactionController}.\n */\nexport type AllowedEvents = NetworkControllerStateChangeEvent;\n\n/**\n * Represents the `TransactionController:stateChange` event.\n */\nexport type TransactionControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n TransactionControllerState\n>;\n\n/**\n * Represents the `TransactionController:incomingTransactionBlockReceived` event.\n */\nexport type TransactionControllerIncomingTransactionBlockReceivedEvent = {\n type: `${typeof controllerName}:incomingTransactionBlockReceived`;\n payload: [blockNumber: number];\n};\n\n/**\n * Represents the `TransactionController:postTransactionBalanceUpdated` event.\n */\nexport type TransactionControllerPostTransactionBalanceUpdatedEvent = {\n type: `${typeof controllerName}:postTransactionBalanceUpdated`;\n payload: [\n {\n transactionMeta: TransactionMeta;\n approvalTransactionMeta?: TransactionMeta;\n },\n ];\n};\n\n/**\n * Represents the `TransactionController:speedUpTransactionAdded` event.\n */\nexport type TransactionControllerSpeedupTransactionAddedEvent = {\n type: `${typeof controllerName}:speedupTransactionAdded`;\n payload: [transactionMeta: TransactionMeta];\n};\n\n/**\n * Represents the `TransactionController:transactionApproved` event.\n */\nexport type TransactionControllerTransactionApprovedEvent = {\n type: `${typeof controllerName}:transactionApproved`;\n payload: [\n {\n transactionMeta: TransactionMeta;\n actionId?: string;\n },\n ];\n};\n\n/**\n * Represents the `TransactionController:transactionConfirmed` event.\n */\nexport type TransactionControllerTransactionConfirmedEvent = {\n type: `${typeof controllerName}:transactionConfirmed`;\n payload: [transactionMeta: TransactionMeta];\n};\n\n/**\n * Represents the `TransactionController:transactionDropped` event.\n */\nexport type TransactionControllerTransactionDroppedEvent = {\n type: `${typeof controllerName}:transactionDropped`;\n payload: [{ transactionMeta: TransactionMeta }];\n};\n\n/**\n * Represents the `TransactionController:transactionFailed` event.\n */\nexport type TransactionControllerTransactionFailedEvent = {\n type: `${typeof controllerName}:transactionFailed`;\n payload: [\n {\n actionId?: string;\n error: string;\n transactionMeta: TransactionMeta;\n },\n ];\n};\n\n/**\n * Represents the `TransactionController:transactionFinished` event.\n */\nexport type TransactionControllerTransactionFinishedEvent = {\n type: `${typeof controllerName}:transactionFinished`;\n payload: [transactionMeta: TransactionMeta];\n};\n\n/**\n * Represents the `TransactionController:transactionNewSwapApproval` event.\n */\nexport type TransactionControllerTransactionNewSwapApprovalEvent = {\n type: `${typeof controllerName}:transactionNewSwapApproval`;\n payload: [{ transactionMeta: TransactionMeta }];\n};\n\n/**\n * Represents the `TransactionController:transactionNewSwap` event.\n */\nexport type TransactionControllerTransactionNewSwapEvent = {\n type: `${typeof controllerName}:transactionNewSwap`;\n payload: [{ transactionMeta: TransactionMeta }];\n};\n\n/**\n * Represents the `TransactionController:transactionNewSwapApproval` event.\n */\nexport type TransactionControllerTransactionNewSwapAndSendEvent = {\n type: `${typeof controllerName}:transactionNewSwapAndSend`;\n payload: [{ transactionMeta: TransactionMeta }];\n};\n\n/**\n * Represents the `TransactionController:transactionPublishingSkipped` event.\n */\nexport type TransactionControllerTransactionPublishingSkipped = {\n type: `${typeof controllerName}:transactionPublishingSkipped`;\n payload: [transactionMeta: TransactionMeta];\n};\n\n/**\n * Represents the `TransactionController:transactionRejected` event.\n */\nexport type TransactionControllerTransactionRejectedEvent = {\n type: `${typeof controllerName}:transactionRejected`;\n payload: [\n {\n transactionMeta: TransactionMeta;\n actionId?: string;\n },\n ];\n};\n\n/**\n * Represents the `TransactionController:transactionStatusUpdated` event.\n */\nexport type TransactionControllerTransactionStatusUpdatedEvent = {\n type: `${typeof controllerName}:transactionStatusUpdated`;\n payload: [\n {\n transactionMeta: TransactionMeta;\n },\n ];\n};\n\n/**\n * Represents the `TransactionController:transactionSubmitted` event.\n */\nexport type TransactionControllerTransactionSubmittedEvent = {\n type: `${typeof controllerName}:transactionSubmitted`;\n payload: [\n {\n transactionMeta: TransactionMeta;\n actionId?: string;\n },\n ];\n};\n\n/**\n * Represents the `TransactionController:unapprovedTransactionAdded` event.\n */\nexport type TransactionControllerUnapprovedTransactionAddedEvent = {\n type: `${typeof controllerName}:unapprovedTransactionAdded`;\n payload: [transactionMeta: TransactionMeta];\n};\n\n/**\n * The internal events available to the {@link TransactionController}.\n */\nexport type TransactionControllerEvents =\n | TransactionControllerIncomingTransactionBlockReceivedEvent\n | TransactionControllerPostTransactionBalanceUpdatedEvent\n | TransactionControllerSpeedupTransactionAddedEvent\n | TransactionControllerStateChangeEvent\n | TransactionControllerTransactionApprovedEvent\n | TransactionControllerTransactionConfirmedEvent\n | TransactionControllerTransactionDroppedEvent\n | TransactionControllerTransactionFailedEvent\n | TransactionControllerTransactionFinishedEvent\n | TransactionControllerTransactionNewSwapApprovalEvent\n | TransactionControllerTransactionNewSwapEvent\n | TransactionControllerTransactionNewSwapAndSendEvent\n | TransactionControllerTransactionPublishingSkipped\n | TransactionControllerTransactionRejectedEvent\n | TransactionControllerTransactionStatusUpdatedEvent\n | TransactionControllerTransactionSubmittedEvent\n | TransactionControllerUnapprovedTransactionAddedEvent;\n\n/**\n * The messenger of the {@link TransactionController}.\n */\nexport type TransactionControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n TransactionControllerActions | AllowedActions,\n TransactionControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Possible states of the approve transaction step.\n */\nexport enum ApprovalState {\n Approved = 'approved',\n NotApproved = 'not-approved',\n SkippedViaBeforePublishHook = 'skipped-via-before-publish-hook',\n}\n\n/**\n * Get the default TransactionsController state.\n *\n * @returns The default TransactionsController state.\n */\nfunction getDefaultTransactionControllerState(): TransactionControllerState {\n return {\n methodData: {},\n transactions: [],\n lastFetchedBlockNumbers: {},\n };\n}\n\n/**\n * Controller responsible for submitting and managing transactions.\n */\nexport class TransactionController extends BaseController<\n typeof controllerName,\n TransactionControllerState,\n TransactionControllerMessenger\n> {\n #internalEvents = new EventEmitter();\n\n private readonly isHistoryDisabled: boolean;\n\n private readonly isSwapsDisabled: boolean;\n\n private readonly isSendFlowHistoryDisabled: boolean;\n\n private readonly approvingTransactionIds: Set = new Set();\n\n private readonly nonceTracker: NonceTracker;\n\n private readonly registry: MethodRegistry;\n\n private readonly mutex = new Mutex();\n\n private readonly gasFeeFlows: GasFeeFlow[];\n\n private readonly getSavedGasFees: (chainId: Hex) => SavedGasFees | undefined;\n\n private readonly getNetworkState: () => NetworkState;\n\n private readonly getCurrentAccountEIP1559Compatibility: () => Promise;\n\n private readonly getCurrentNetworkEIP1559Compatibility: (\n networkClientId?: NetworkClientId,\n ) => Promise;\n\n private readonly getGasFeeEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise;\n\n private readonly getPermittedAccounts: (origin?: string) => Promise;\n\n private readonly getExternalPendingTransactions: (\n address: string,\n chainId?: string,\n ) => NonceTrackerTransaction[];\n\n private readonly layer1GasFeeFlows: Layer1GasFeeFlow[];\n\n readonly #incomingTransactionOptions: IncomingTransactionOptions;\n\n private readonly incomingTransactionHelper: IncomingTransactionHelper;\n\n private readonly securityProviderRequest?: SecurityProviderRequest;\n\n readonly #pendingTransactionOptions: PendingTransactionOptions;\n\n private readonly pendingTransactionTracker: PendingTransactionTracker;\n\n private readonly signAbortCallbacks: Map void> = new Map();\n\n #transactionHistoryLimit: number;\n\n #isSimulationEnabled: () => boolean;\n\n #testGasFeeFlows: boolean;\n\n private readonly afterSign: (\n transactionMeta: TransactionMeta,\n signedTx: TypedTransaction,\n ) => boolean;\n\n private readonly beforeCheckPendingTransaction: (\n transactionMeta: TransactionMeta,\n ) => boolean;\n\n private readonly beforePublish: (transactionMeta: TransactionMeta) => boolean;\n\n private readonly publish: (\n transactionMeta: TransactionMeta,\n rawTx: string,\n ) => Promise<{ transactionHash?: string }>;\n\n private readonly getAdditionalSignArguments: (\n transactionMeta: TransactionMeta,\n ) => (TransactionMeta | undefined)[];\n\n private failTransaction(\n transactionMeta: TransactionMeta,\n error: Error,\n actionId?: string,\n ) {\n let newTransactionMeta: TransactionMeta;\n\n try {\n newTransactionMeta = this.#updateTransactionInternal(\n {\n transactionId: transactionMeta.id,\n note: 'TransactionController#failTransaction - Add error message and set status to failed',\n skipValidation: true,\n },\n (draftTransactionMeta) => {\n draftTransactionMeta.status = TransactionStatus.failed;\n\n (\n draftTransactionMeta as TransactionMeta & {\n status: TransactionStatus.failed;\n }\n ).error = normalizeTxError(error);\n },\n );\n } catch (err: unknown) {\n log('Failed to mark transaction as failed', err);\n\n newTransactionMeta = {\n ...transactionMeta,\n status: TransactionStatus.failed,\n error: normalizeTxError(error),\n };\n }\n\n this.messagingSystem.publish(`${controllerName}:transactionFailed`, {\n actionId,\n error: error.message,\n transactionMeta: newTransactionMeta,\n });\n\n this.onTransactionStatusChange(newTransactionMeta);\n\n this.messagingSystem.publish(\n `${controllerName}:transactionFinished`,\n newTransactionMeta,\n );\n\n this.#internalEvents.emit(\n `${transactionMeta.id}:finished`,\n newTransactionMeta,\n );\n }\n\n private async registryLookup(fourBytePrefix: string): Promise {\n const registryMethod = await this.registry.lookup(fourBytePrefix);\n if (!registryMethod) {\n return {\n registryMethod: '',\n parsedRegistryMethod: { name: undefined, args: undefined },\n };\n }\n const parsedRegistryMethod = this.registry.parse(registryMethod);\n return { registryMethod, parsedRegistryMethod };\n }\n\n #multichainTrackingHelper: MultichainTrackingHelper;\n\n /**\n * Method used to sign transactions\n */\n sign?: (\n transaction: TypedTransaction,\n from: string,\n transactionMeta?: TransactionMeta,\n ) => Promise;\n\n /**\n * Constructs a TransactionController.\n *\n * @param options - The controller options.\n * @param options.blockTracker - The block tracker used to poll for new blocks data.\n * @param options.disableHistory - Whether to disable storing history in transaction metadata.\n * @param options.disableSendFlowHistory - Explicitly disable transaction metadata history.\n * @param options.disableSwaps - Whether to disable additional processing on swaps transactions.\n * @param options.getCurrentAccountEIP1559Compatibility - Whether or not the account supports EIP-1559.\n * @param options.getCurrentNetworkEIP1559Compatibility - Whether or not the network supports EIP-1559.\n * @param options.getExternalPendingTransactions - Callback to retrieve pending transactions from external sources.\n * @param options.getGasFeeEstimates - Callback to retrieve gas fee estimates.\n * @param options.getNetworkClientRegistry - Gets the network client registry.\n * @param options.getNetworkState - Gets the state of the network controller.\n * @param options.getPermittedAccounts - Get accounts that a given origin has permissions for.\n * @param options.getSavedGasFees - Gets the saved gas fee config.\n * @param options.incomingTransactions - Configuration options for incoming transaction support.\n * @param options.isMultichainEnabled - Enable multichain support.\n * @param options.isSimulationEnabled - Whether new transactions will be automatically simulated.\n * @param options.messenger - The controller messenger.\n * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.\n * @param options.pendingTransactions - Configuration options for pending transaction support.\n * @param options.provider - The provider used to create the underlying EthQuery instance.\n * @param options.securityProviderRequest - A function for verifying a transaction, whether it is malicious or not.\n * @param options.sign - Function used to sign transactions.\n * @param options.state - Initial state to set on this controller.\n * @param options.testGasFeeFlows - Whether to use the test gas fee flow.\n * @param options.transactionHistoryLimit - Transaction history limit.\n * @param options.hooks - The controller hooks.\n */\n constructor({\n blockTracker,\n disableHistory,\n disableSendFlowHistory,\n disableSwaps,\n getCurrentAccountEIP1559Compatibility,\n getCurrentNetworkEIP1559Compatibility,\n getExternalPendingTransactions,\n getGasFeeEstimates,\n getNetworkClientRegistry,\n getNetworkState,\n getPermittedAccounts,\n getSavedGasFees,\n incomingTransactions = {},\n isMultichainEnabled = false,\n isSimulationEnabled,\n messenger,\n onNetworkStateChange,\n pendingTransactions = {},\n provider,\n securityProviderRequest,\n sign,\n state,\n testGasFeeFlows,\n transactionHistoryLimit = 40,\n hooks,\n }: TransactionControllerOptions) {\n super({\n name: controllerName,\n metadata,\n messenger,\n state: {\n ...getDefaultTransactionControllerState(),\n ...state,\n },\n });\n\n this.messagingSystem = messenger;\n this.getNetworkState = getNetworkState;\n this.isSendFlowHistoryDisabled = disableSendFlowHistory ?? false;\n this.isHistoryDisabled = disableHistory ?? false;\n this.isSwapsDisabled = disableSwaps ?? false;\n this.#isSimulationEnabled = isSimulationEnabled ?? (() => true);\n // @ts-expect-error the type in eth-method-registry is inappropriate and should be changed\n this.registry = new MethodRegistry({ provider });\n this.getSavedGasFees = getSavedGasFees ?? ((_chainId) => undefined);\n this.getCurrentAccountEIP1559Compatibility =\n getCurrentAccountEIP1559Compatibility ?? (() => Promise.resolve(true));\n this.getCurrentNetworkEIP1559Compatibility =\n getCurrentNetworkEIP1559Compatibility;\n this.getGasFeeEstimates =\n getGasFeeEstimates || (() => Promise.resolve({} as GasFeeState));\n this.getPermittedAccounts = getPermittedAccounts;\n this.getExternalPendingTransactions =\n getExternalPendingTransactions ?? (() => []);\n this.securityProviderRequest = securityProviderRequest;\n this.#incomingTransactionOptions = incomingTransactions;\n this.#pendingTransactionOptions = pendingTransactions;\n this.#transactionHistoryLimit = transactionHistoryLimit;\n this.sign = sign;\n this.#testGasFeeFlows = testGasFeeFlows === true;\n\n this.afterSign = hooks?.afterSign ?? (() => true);\n this.beforeCheckPendingTransaction =\n hooks?.beforeCheckPendingTransaction ??\n /* istanbul ignore next */\n (() => true);\n this.beforePublish = hooks?.beforePublish ?? (() => true);\n this.getAdditionalSignArguments =\n hooks?.getAdditionalSignArguments ?? (() => []);\n this.publish =\n hooks?.publish ?? (() => Promise.resolve({ transactionHash: undefined }));\n\n this.nonceTracker = this.#createNonceTracker({\n provider,\n blockTracker,\n });\n\n const findNetworkClientIdByChainId = (chainId: Hex) => {\n return this.messagingSystem.call(\n `NetworkController:findNetworkClientIdByChainId`,\n chainId,\n );\n };\n\n this.#multichainTrackingHelper = new MultichainTrackingHelper({\n isMultichainEnabled,\n provider,\n nonceTracker: this.nonceTracker,\n incomingTransactionOptions: incomingTransactions,\n findNetworkClientIdByChainId,\n getNetworkClientById: ((networkClientId: NetworkClientId) => {\n return this.messagingSystem.call(\n `NetworkController:getNetworkClientById`,\n networkClientId,\n );\n }) as NetworkController['getNetworkClientById'],\n getNetworkClientRegistry,\n removeIncomingTransactionHelperListeners:\n this.#removeIncomingTransactionHelperListeners.bind(this),\n removePendingTransactionTrackerListeners:\n this.#removePendingTransactionTrackerListeners.bind(this),\n createNonceTracker: this.#createNonceTracker.bind(this),\n createIncomingTransactionHelper:\n this.#createIncomingTransactionHelper.bind(this),\n createPendingTransactionTracker:\n this.#createPendingTransactionTracker.bind(this),\n onNetworkStateChange: (listener) => {\n this.messagingSystem.subscribe(\n 'NetworkController:stateChange',\n listener,\n );\n },\n });\n this.#multichainTrackingHelper.initialize();\n\n const etherscanRemoteTransactionSource =\n new EtherscanRemoteTransactionSource({\n includeTokenTransfers: incomingTransactions.includeTokenTransfers,\n });\n\n this.incomingTransactionHelper = this.#createIncomingTransactionHelper({\n blockTracker,\n etherscanRemoteTransactionSource,\n });\n\n this.pendingTransactionTracker = this.#createPendingTransactionTracker({\n provider,\n blockTracker,\n });\n\n this.gasFeeFlows = this.#getGasFeeFlows();\n this.layer1GasFeeFlows = this.#getLayer1GasFeeFlows();\n\n const gasFeePoller = new GasFeePoller({\n findNetworkClientIdByChainId,\n gasFeeFlows: this.gasFeeFlows,\n getGasFeeControllerEstimates: this.getGasFeeEstimates,\n getProvider: (chainId, networkClientId) =>\n this.#multichainTrackingHelper.getProvider({\n networkClientId,\n chainId,\n }),\n getTransactions: () => this.state.transactions,\n layer1GasFeeFlows: this.layer1GasFeeFlows,\n onStateChange: (listener) => {\n this.messagingSystem.subscribe(\n 'TransactionController:stateChange',\n listener,\n );\n },\n });\n\n gasFeePoller.hub.on(\n 'transaction-updated',\n this.#onGasFeePollerTransactionUpdate.bind(this),\n );\n\n // when transactionsController state changes\n // check for pending transactions and start polling if there are any\n this.messagingSystem.subscribe(\n 'TransactionController:stateChange',\n this.#checkForPendingTransactionAndStartPolling,\n );\n\n // TODO once v2 is merged make sure this only runs when\n // selectedNetworkClientId changes\n onNetworkStateChange(() => {\n log('Detected network change', this.getChainId());\n this.pendingTransactionTracker.startIfPendingTransactions();\n this.onBootCleanup();\n });\n\n this.onBootCleanup();\n this.#checkForPendingTransactionAndStartPolling();\n }\n\n /**\n * Stops polling and removes listeners to prepare the controller for garbage collection.\n */\n destroy() {\n this.#stopAllTracking();\n }\n\n /**\n * Handle new method data request.\n *\n * @param fourBytePrefix - The method prefix.\n * @returns The method data object corresponding to the given signature prefix.\n */\n async handleMethodData(fourBytePrefix: string): Promise {\n const releaseLock = await this.mutex.acquire();\n try {\n const { methodData } = this.state;\n const knownMethod = Object.keys(methodData).find(\n (knownFourBytePrefix) => fourBytePrefix === knownFourBytePrefix,\n );\n if (knownMethod) {\n return methodData[fourBytePrefix];\n }\n const registry = await this.registryLookup(fourBytePrefix);\n this.update((state) => {\n state.methodData[fourBytePrefix] = registry;\n });\n return registry;\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Add a new unapproved transaction to state. Parameters will be validated, a\n * unique transaction id will be generated, and gas and gasPrice will be calculated\n * if not provided. If A `:unapproved` hub event will be emitted once added.\n *\n * @param txParams - Standard parameters for an Ethereum transaction.\n * @param opts - Additional options to control how the transaction is added.\n * @param opts.actionId - Unique ID to prevent duplicate requests.\n * @param opts.deviceConfirmedOn - An enum to indicate what device confirmed the transaction.\n * @param opts.method - RPC method that requested the transaction.\n * @param opts.origin - The origin of the transaction request, such as a dApp hostname.\n * @param opts.requireApproval - Whether the transaction requires approval by the user, defaults to true unless explicitly disabled.\n * @param opts.securityAlertResponse - Response from security validator.\n * @param opts.sendFlowHistory - The sendFlowHistory entries to add.\n * @param opts.type - Type of transaction to add, such as 'cancel' or 'swap'.\n * @param opts.swaps - Options for swaps transactions.\n * @param opts.swaps.hasApproveTx - Whether the transaction has an approval transaction.\n * @param opts.swaps.meta - Metadata for swap transaction.\n * @param opts.networkClientId - The id of the network client for this transaction.\n * @returns Object containing a promise resolving to the transaction hash if approved.\n */\n async addTransaction(\n txParams: TransactionParams,\n {\n actionId,\n deviceConfirmedOn,\n method,\n origin,\n requireApproval,\n securityAlertResponse,\n sendFlowHistory,\n swaps = {},\n type,\n networkClientId: requestNetworkClientId,\n }: {\n actionId?: string;\n deviceConfirmedOn?: WalletDevice;\n method?: string;\n origin?: string;\n requireApproval?: boolean | undefined;\n securityAlertResponse?: SecurityAlertResponse;\n sendFlowHistory?: SendFlowHistoryEntry[];\n swaps?: {\n hasApproveTx?: boolean;\n meta?: Partial;\n };\n type?: TransactionType;\n networkClientId?: NetworkClientId;\n } = {},\n ): Promise {\n log('Adding transaction', txParams);\n\n txParams = normalizeTransactionParams(txParams);\n if (\n requestNetworkClientId &&\n !this.#multichainTrackingHelper.has(requestNetworkClientId)\n ) {\n throw new Error(\n 'The networkClientId for this transaction could not be found',\n );\n }\n\n const networkClientId =\n requestNetworkClientId ?? this.#getGlobalNetworkClientId();\n\n const isEIP1559Compatible = await this.getEIP1559Compatibility(\n networkClientId,\n );\n\n validateTxParams(txParams, isEIP1559Compatible);\n\n if (origin) {\n await validateTransactionOrigin(\n await this.getPermittedAccounts(origin),\n this.#getSelectedAccount().address,\n txParams.from,\n origin,\n );\n }\n\n const dappSuggestedGasFees = this.generateDappSuggestedGasFees(\n txParams,\n origin,\n );\n\n const chainId = this.getChainId(networkClientId);\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId,\n chainId,\n });\n\n const transactionType =\n type ?? (await determineTransactionType(txParams, ethQuery)).type;\n\n const existingTransactionMeta = this.getTransactionWithActionId(actionId);\n\n // If a request to add a transaction with the same actionId is submitted again, a new transaction will not be created for it.\n let addedTransactionMeta = existingTransactionMeta\n ? cloneDeep(existingTransactionMeta)\n : {\n // Add actionId to txMeta to check if same actionId is seen again\n actionId,\n chainId,\n dappSuggestedGasFees,\n deviceConfirmedOn,\n id: random(),\n origin,\n securityAlertResponse,\n status: TransactionStatus.unapproved as const,\n time: Date.now(),\n txParams,\n userEditedGasLimit: false,\n verifiedOnBlockchain: false,\n type: transactionType,\n networkClientId,\n };\n\n await this.updateGasProperties(addedTransactionMeta);\n\n // Checks if a transaction already exists with a given actionId\n if (!existingTransactionMeta) {\n // Set security provider response\n if (method && this.securityProviderRequest) {\n const securityProviderResponse = await this.securityProviderRequest(\n addedTransactionMeta,\n method,\n );\n addedTransactionMeta.securityProviderResponse =\n securityProviderResponse;\n }\n\n if (!this.isSendFlowHistoryDisabled) {\n addedTransactionMeta.sendFlowHistory = sendFlowHistory ?? [];\n }\n // Initial history push\n if (!this.isHistoryDisabled) {\n addedTransactionMeta = addInitialHistorySnapshot(addedTransactionMeta);\n }\n\n addedTransactionMeta = updateSwapsTransaction(\n addedTransactionMeta,\n transactionType,\n swaps,\n {\n isSwapsDisabled: this.isSwapsDisabled,\n cancelTransaction: this.cancelTransaction.bind(this),\n messenger: this.messagingSystem,\n },\n );\n\n this.addMetadata(addedTransactionMeta);\n\n if (requireApproval !== false) {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#updateSimulationData(addedTransactionMeta);\n } else {\n log('Skipping simulation as approval not required');\n }\n\n this.messagingSystem.publish(\n `${controllerName}:unapprovedTransactionAdded`,\n addedTransactionMeta,\n );\n }\n\n return {\n result: this.processApproval(addedTransactionMeta, {\n isExisting: Boolean(existingTransactionMeta),\n requireApproval,\n actionId,\n }),\n transactionMeta: addedTransactionMeta,\n };\n }\n\n startIncomingTransactionPolling(networkClientIds: NetworkClientId[] = []) {\n if (networkClientIds.length === 0) {\n this.incomingTransactionHelper.start();\n return;\n }\n this.#multichainTrackingHelper.startIncomingTransactionPolling(\n networkClientIds,\n );\n }\n\n stopIncomingTransactionPolling(networkClientIds: NetworkClientId[] = []) {\n if (networkClientIds.length === 0) {\n this.incomingTransactionHelper.stop();\n return;\n }\n this.#multichainTrackingHelper.stopIncomingTransactionPolling(\n networkClientIds,\n );\n }\n\n stopAllIncomingTransactionPolling() {\n this.incomingTransactionHelper.stop();\n this.#multichainTrackingHelper.stopAllIncomingTransactionPolling();\n }\n\n async updateIncomingTransactions(networkClientIds: NetworkClientId[] = []) {\n if (networkClientIds.length === 0) {\n await this.incomingTransactionHelper.update();\n return;\n }\n await this.#multichainTrackingHelper.updateIncomingTransactions(\n networkClientIds,\n );\n }\n\n /**\n * Attempts to cancel a transaction based on its ID by setting its status to \"rejected\"\n * and emitting a `:finished` hub event.\n *\n * @param transactionId - The ID of the transaction to cancel.\n * @param gasValues - The gas values to use for the cancellation transaction.\n * @param options - The options for the cancellation transaction.\n * @param options.actionId - Unique ID to prevent duplicate requests.\n * @param options.estimatedBaseFee - The estimated base fee of the transaction.\n */\n async stopTransaction(\n transactionId: string,\n gasValues?: GasPriceValue | FeeMarketEIP1559Values,\n {\n estimatedBaseFee,\n actionId,\n }: { estimatedBaseFee?: string; actionId?: string } = {},\n ) {\n // If transaction is found for same action id, do not create a cancel transaction.\n if (this.getTransactionWithActionId(actionId)) {\n return;\n }\n\n if (gasValues) {\n // Not good practice to reassign a parameter but temporarily avoiding a larger refactor.\n gasValues = normalizeGasFeeValues(gasValues);\n validateGasValues(gasValues);\n }\n\n log('Creating cancel transaction', transactionId, gasValues);\n\n const transactionMeta = this.getTransaction(transactionId);\n if (!transactionMeta) {\n return;\n }\n\n if (!this.sign) {\n throw new Error('No sign method defined.');\n }\n\n // gasPrice (legacy non EIP1559)\n const minGasPrice = getIncreasedPriceFromExisting(\n transactionMeta.txParams.gasPrice,\n CANCEL_RATE,\n );\n\n const gasPriceFromValues = isGasPriceValue(gasValues) && gasValues.gasPrice;\n\n const newGasPrice =\n (gasPriceFromValues &&\n validateMinimumIncrease(gasPriceFromValues, minGasPrice)) ||\n minGasPrice;\n\n // maxFeePerGas (EIP1559)\n const existingMaxFeePerGas = transactionMeta.txParams?.maxFeePerGas;\n const minMaxFeePerGas = getIncreasedPriceFromExisting(\n existingMaxFeePerGas,\n CANCEL_RATE,\n );\n const maxFeePerGasValues =\n isFeeMarketEIP1559Values(gasValues) && gasValues.maxFeePerGas;\n const newMaxFeePerGas =\n (maxFeePerGasValues &&\n validateMinimumIncrease(maxFeePerGasValues, minMaxFeePerGas)) ||\n (existingMaxFeePerGas && minMaxFeePerGas);\n\n // maxPriorityFeePerGas (EIP1559)\n const existingMaxPriorityFeePerGas =\n transactionMeta.txParams?.maxPriorityFeePerGas;\n const minMaxPriorityFeePerGas = getIncreasedPriceFromExisting(\n existingMaxPriorityFeePerGas,\n CANCEL_RATE,\n );\n const maxPriorityFeePerGasValues =\n isFeeMarketEIP1559Values(gasValues) && gasValues.maxPriorityFeePerGas;\n const newMaxPriorityFeePerGas =\n (maxPriorityFeePerGasValues &&\n validateMinimumIncrease(\n maxPriorityFeePerGasValues,\n minMaxPriorityFeePerGas,\n )) ||\n (existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas);\n\n const newTxParams: TransactionParams =\n newMaxFeePerGas && newMaxPriorityFeePerGas\n ? {\n from: transactionMeta.txParams.from,\n gasLimit: transactionMeta.txParams.gas,\n maxFeePerGas: newMaxFeePerGas,\n maxPriorityFeePerGas: newMaxPriorityFeePerGas,\n type: TransactionEnvelopeType.feeMarket,\n nonce: transactionMeta.txParams.nonce,\n to: transactionMeta.txParams.from,\n value: '0x0',\n }\n : {\n from: transactionMeta.txParams.from,\n gasLimit: transactionMeta.txParams.gas,\n gasPrice: newGasPrice,\n nonce: transactionMeta.txParams.nonce,\n to: transactionMeta.txParams.from,\n value: '0x0',\n };\n\n const unsignedEthTx = this.prepareUnsignedEthTx(\n transactionMeta.chainId,\n newTxParams,\n );\n\n const signedTx = await this.sign(\n unsignedEthTx,\n transactionMeta.txParams.from,\n );\n\n const rawTx = bufferToHex(signedTx.serialize());\n\n const newFee = newTxParams.maxFeePerGas ?? newTxParams.gasPrice;\n\n const oldFee = newTxParams.maxFeePerGas\n ? transactionMeta.txParams.maxFeePerGas\n : transactionMeta.txParams.gasPrice;\n\n log('Submitting cancel transaction', {\n oldFee,\n newFee,\n txParams: newTxParams,\n });\n\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId: transactionMeta.networkClientId,\n chainId: transactionMeta.chainId,\n });\n const hash = await this.publishTransactionForRetry(\n ethQuery,\n rawTx,\n transactionMeta,\n );\n\n const cancelTransactionMeta = {\n actionId,\n chainId: transactionMeta.chainId,\n networkClientId: transactionMeta.networkClientId,\n estimatedBaseFee,\n hash,\n id: random(),\n originalGasEstimate: transactionMeta.txParams.gas,\n rawTx,\n status: TransactionStatus.submitted as const,\n time: Date.now(),\n type: TransactionType.cancel as const,\n txParams: newTxParams,\n };\n\n this.addMetadata(cancelTransactionMeta);\n\n // stopTransaction has no approval request, so we assume the user has already approved the transaction\n this.messagingSystem.publish(`${controllerName}:transactionApproved`, {\n transactionMeta: cancelTransactionMeta,\n actionId,\n });\n this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {\n transactionMeta: cancelTransactionMeta,\n actionId,\n });\n\n this.messagingSystem.publish(\n `${controllerName}:transactionFinished`,\n cancelTransactionMeta,\n );\n this.#internalEvents.emit(\n `${transactionMeta.id}:finished`,\n cancelTransactionMeta,\n );\n }\n\n /**\n * Attempts to speed up a transaction increasing transaction gasPrice by ten percent.\n *\n * @param transactionId - The ID of the transaction to speed up.\n * @param gasValues - The gas values to use for the speed up transaction.\n * @param options - The options for the speed up transaction.\n * @param options.actionId - Unique ID to prevent duplicate requests\n * @param options.estimatedBaseFee - The estimated base fee of the transaction.\n */\n async speedUpTransaction(\n transactionId: string,\n gasValues?: GasPriceValue | FeeMarketEIP1559Values,\n {\n actionId,\n estimatedBaseFee,\n }: { actionId?: string; estimatedBaseFee?: string } = {},\n ) {\n // If transaction is found for same action id, do not create a new speed up transaction.\n if (this.getTransactionWithActionId(actionId)) {\n return;\n }\n\n if (gasValues) {\n // Not good practice to reassign a parameter but temporarily avoiding a larger refactor.\n gasValues = normalizeGasFeeValues(gasValues);\n validateGasValues(gasValues);\n }\n\n log('Creating speed up transaction', transactionId, gasValues);\n\n const transactionMeta = this.getTransaction(transactionId);\n /* istanbul ignore next */\n if (!transactionMeta) {\n return;\n }\n\n /* istanbul ignore next */\n if (!this.sign) {\n throw new Error('No sign method defined.');\n }\n\n // gasPrice (legacy non EIP1559)\n const minGasPrice = getIncreasedPriceFromExisting(\n transactionMeta.txParams.gasPrice,\n SPEED_UP_RATE,\n );\n\n const gasPriceFromValues = isGasPriceValue(gasValues) && gasValues.gasPrice;\n\n const newGasPrice =\n (gasPriceFromValues &&\n validateMinimumIncrease(gasPriceFromValues, minGasPrice)) ||\n minGasPrice;\n\n // maxFeePerGas (EIP1559)\n const existingMaxFeePerGas = transactionMeta.txParams?.maxFeePerGas;\n const minMaxFeePerGas = getIncreasedPriceFromExisting(\n existingMaxFeePerGas,\n SPEED_UP_RATE,\n );\n const maxFeePerGasValues =\n isFeeMarketEIP1559Values(gasValues) && gasValues.maxFeePerGas;\n const newMaxFeePerGas =\n (maxFeePerGasValues &&\n validateMinimumIncrease(maxFeePerGasValues, minMaxFeePerGas)) ||\n (existingMaxFeePerGas && minMaxFeePerGas);\n\n // maxPriorityFeePerGas (EIP1559)\n const existingMaxPriorityFeePerGas =\n transactionMeta.txParams?.maxPriorityFeePerGas;\n const minMaxPriorityFeePerGas = getIncreasedPriceFromExisting(\n existingMaxPriorityFeePerGas,\n SPEED_UP_RATE,\n );\n const maxPriorityFeePerGasValues =\n isFeeMarketEIP1559Values(gasValues) && gasValues.maxPriorityFeePerGas;\n const newMaxPriorityFeePerGas =\n (maxPriorityFeePerGasValues &&\n validateMinimumIncrease(\n maxPriorityFeePerGasValues,\n minMaxPriorityFeePerGas,\n )) ||\n (existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas);\n\n const txParams: TransactionParams =\n newMaxFeePerGas && newMaxPriorityFeePerGas\n ? {\n ...transactionMeta.txParams,\n gasLimit: transactionMeta.txParams.gas,\n maxFeePerGas: newMaxFeePerGas,\n maxPriorityFeePerGas: newMaxPriorityFeePerGas,\n type: TransactionEnvelopeType.feeMarket,\n }\n : {\n ...transactionMeta.txParams,\n gasLimit: transactionMeta.txParams.gas,\n gasPrice: newGasPrice,\n };\n\n const unsignedEthTx = this.prepareUnsignedEthTx(\n transactionMeta.chainId,\n txParams,\n );\n\n const signedTx = await this.sign(\n unsignedEthTx,\n transactionMeta.txParams.from,\n );\n\n const transactionMetaWithRsv = this.updateTransactionMetaRSV(\n transactionMeta,\n signedTx,\n );\n const rawTx = bufferToHex(signedTx.serialize());\n\n const newFee = txParams.maxFeePerGas ?? txParams.gasPrice;\n\n const oldFee = txParams.maxFeePerGas\n ? transactionMetaWithRsv.txParams.maxFeePerGas\n : transactionMetaWithRsv.txParams.gasPrice;\n\n log('Submitting speed up transaction', { oldFee, newFee, txParams });\n\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId: transactionMeta.networkClientId,\n chainId: transactionMeta.chainId,\n });\n const hash = await this.publishTransactionForRetry(\n ethQuery,\n rawTx,\n transactionMeta,\n );\n\n const baseTransactionMeta = {\n ...transactionMetaWithRsv,\n estimatedBaseFee,\n id: random(),\n time: Date.now(),\n hash,\n actionId,\n originalGasEstimate: transactionMeta.txParams.gas,\n type: TransactionType.retry as const,\n originalType: transactionMeta.type,\n };\n\n const newTransactionMeta =\n newMaxFeePerGas && newMaxPriorityFeePerGas\n ? {\n ...baseTransactionMeta,\n txParams: {\n ...transactionMeta.txParams,\n maxFeePerGas: newMaxFeePerGas,\n maxPriorityFeePerGas: newMaxPriorityFeePerGas,\n },\n }\n : {\n ...baseTransactionMeta,\n txParams: {\n ...transactionMeta.txParams,\n gasPrice: newGasPrice,\n },\n };\n\n this.addMetadata(newTransactionMeta);\n\n // speedUpTransaction has no approval request, so we assume the user has already approved the transaction\n this.messagingSystem.publish(`${controllerName}:transactionApproved`, {\n transactionMeta: newTransactionMeta,\n actionId,\n });\n\n this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {\n transactionMeta: newTransactionMeta,\n actionId,\n });\n\n this.messagingSystem.publish(\n `${controllerName}:speedupTransactionAdded`,\n newTransactionMeta,\n );\n }\n\n /**\n * Estimates required gas for a given transaction.\n *\n * @param transaction - The transaction to estimate gas for.\n * @param networkClientId - The network client id to use for the estimate.\n * @returns The gas and gas price.\n */\n async estimateGas(\n transaction: TransactionParams,\n networkClientId?: NetworkClientId,\n ) {\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId,\n });\n const { estimatedGas, simulationFails } = await estimateGas(\n transaction,\n ethQuery,\n );\n\n return { gas: estimatedGas, simulationFails };\n }\n\n /**\n * Estimates required gas for a given transaction and add additional gas buffer with the given multiplier.\n *\n * @param transaction - The transaction params to estimate gas for.\n * @param multiplier - The multiplier to use for the gas buffer.\n * @param networkClientId - The network client id to use for the estimate.\n */\n async estimateGasBuffered(\n transaction: TransactionParams,\n multiplier: number,\n networkClientId?: NetworkClientId,\n ) {\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId,\n });\n const { blockGasLimit, estimatedGas, simulationFails } = await estimateGas(\n transaction,\n ethQuery,\n );\n\n const gas = addGasBuffer(estimatedGas, blockGasLimit, multiplier);\n\n return {\n gas,\n simulationFails,\n };\n }\n\n /**\n * Updates an existing transaction in state.\n *\n * @param transactionMeta - The new transaction to store in state.\n * @param note - A note or update reason to include in the transaction history.\n */\n updateTransaction(transactionMeta: TransactionMeta, note: string) {\n const { id: transactionId } = transactionMeta;\n\n this.#updateTransactionInternal({ transactionId, note }, () => ({\n ...transactionMeta,\n }));\n }\n\n /**\n * Update the security alert response for a transaction.\n *\n * @param transactionId - ID of the transaction.\n * @param securityAlertResponse - The new security alert response for the transaction.\n */\n updateSecurityAlertResponse(\n transactionId: string,\n securityAlertResponse: SecurityAlertResponse,\n ) {\n if (!securityAlertResponse) {\n throw new Error(\n 'updateSecurityAlertResponse: securityAlertResponse should not be null',\n );\n }\n const transactionMeta = this.getTransaction(transactionId);\n if (!transactionMeta) {\n throw new Error(\n `Cannot update security alert response as no transaction metadata found`,\n );\n }\n const updatedTransactionMeta = {\n ...transactionMeta,\n securityAlertResponse,\n };\n this.updateTransaction(\n updatedTransactionMeta,\n `${controllerName}:updatesecurityAlertResponse - securityAlertResponse updated`,\n );\n }\n\n /**\n * Removes all transactions from state, optionally based on the current network.\n *\n * @param ignoreNetwork - Determines whether to wipe all transactions, or just those on the\n * current network. If `true`, all transactions are wiped.\n * @param address - If specified, only transactions originating from this address will be\n * wiped on current network.\n */\n wipeTransactions(ignoreNetwork?: boolean, address?: string) {\n /* istanbul ignore next */\n if (ignoreNetwork && !address) {\n this.update((state) => {\n state.transactions = [];\n });\n return;\n }\n const currentChainId = this.getChainId();\n const newTransactions = this.state.transactions.filter(\n ({ chainId, txParams }) => {\n const isMatchingNetwork = ignoreNetwork || chainId === currentChainId;\n\n if (!isMatchingNetwork) {\n return true;\n }\n\n const isMatchingAddress =\n !address || txParams.from?.toLowerCase() === address.toLowerCase();\n\n return !isMatchingAddress;\n },\n );\n\n this.update((state) => {\n state.transactions = this.trimTransactionsForState(newTransactions);\n });\n }\n\n /**\n * Adds external provided transaction to state as confirmed transaction.\n *\n * @param transactionMeta - TransactionMeta to add transactions.\n * @param transactionReceipt - TransactionReceipt of the external transaction.\n * @param baseFeePerGas - Base fee per gas of the external transaction.\n */\n async confirmExternalTransaction(\n transactionMeta: TransactionMeta,\n transactionReceipt: TransactionReceipt,\n baseFeePerGas: Hex,\n ) {\n // Run validation and add external transaction to state.\n const newTransactionMeta = this.addExternalTransaction(transactionMeta);\n\n try {\n const transactionId = newTransactionMeta.id;\n\n // Make sure status is confirmed and define gasUsed as in receipt.\n const updatedTransactionMeta = {\n ...newTransactionMeta,\n status: TransactionStatus.confirmed as const,\n txReceipt: transactionReceipt,\n };\n if (baseFeePerGas) {\n updatedTransactionMeta.baseFeePerGas = baseFeePerGas;\n }\n\n // Update same nonce local transactions as dropped and define replacedBy properties.\n this.markNonceDuplicatesDropped(transactionId);\n\n // Update external provided transaction with updated gas values and confirmed status.\n this.updateTransaction(\n updatedTransactionMeta,\n `${controllerName}:confirmExternalTransaction - Add external transaction`,\n );\n this.onTransactionStatusChange(updatedTransactionMeta);\n\n // Intentional given potential duration of process.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.updatePostBalance(updatedTransactionMeta);\n\n this.messagingSystem.publish(\n `${controllerName}:transactionConfirmed`,\n updatedTransactionMeta,\n );\n } catch (error) {\n console.error('Failed to confirm external transaction', error);\n }\n }\n\n /**\n * Append new send flow history to a transaction.\n *\n * @param transactionID - The ID of the transaction to update.\n * @param currentSendFlowHistoryLength - The length of the current sendFlowHistory array.\n * @param sendFlowHistoryToAdd - The sendFlowHistory entries to add.\n * @returns The updated transactionMeta.\n */\n updateTransactionSendFlowHistory(\n transactionID: string,\n currentSendFlowHistoryLength: number,\n sendFlowHistoryToAdd: SendFlowHistoryEntry[],\n ): TransactionMeta {\n if (this.isSendFlowHistoryDisabled) {\n throw new Error(\n 'Send flow history is disabled for the current transaction controller',\n );\n }\n\n const transactionMeta = this.getTransaction(transactionID);\n\n if (!transactionMeta) {\n throw new Error(\n `Cannot update send flow history as no transaction metadata found`,\n );\n }\n\n validateIfTransactionUnapproved(\n transactionMeta,\n 'updateTransactionSendFlowHistory',\n );\n\n const sendFlowHistory = transactionMeta.sendFlowHistory ?? [];\n if (currentSendFlowHistoryLength === sendFlowHistory.length) {\n const updatedTransactionMeta = {\n ...transactionMeta,\n sendFlowHistory: [...sendFlowHistory, ...sendFlowHistoryToAdd],\n };\n this.updateTransaction(\n updatedTransactionMeta,\n `${controllerName}:updateTransactionSendFlowHistory - sendFlowHistory updated`,\n );\n }\n\n return this.getTransaction(transactionID) as TransactionMeta;\n }\n\n /**\n * Update the gas values of a transaction.\n *\n * @param transactionId - The ID of the transaction to update.\n * @param gasValues - Gas values to update.\n * @param gasValues.gas - Same as transaction.gasLimit.\n * @param gasValues.gasLimit - Maxmimum number of units of gas to use for this transaction.\n * @param gasValues.gasPrice - Price per gas for legacy transactions.\n * @param gasValues.maxPriorityFeePerGas - Maximum amount per gas to give to validator as incentive.\n * @param gasValues.maxFeePerGas - Maximum amount per gas to pay for the transaction, including the priority fee.\n * @param gasValues.estimateUsed - Which estimate level was used.\n * @param gasValues.estimateSuggested - Which estimate level that the API suggested.\n * @param gasValues.defaultGasEstimates - The default estimate for gas.\n * @param gasValues.originalGasEstimate - Original estimate for gas.\n * @param gasValues.userEditedGasLimit - The gas limit supplied by user.\n * @param gasValues.userFeeLevel - Estimate level user selected.\n * @returns The updated transactionMeta.\n */\n updateTransactionGasFees(\n transactionId: string,\n {\n defaultGasEstimates,\n estimateUsed,\n estimateSuggested,\n gas,\n gasLimit,\n gasPrice,\n maxPriorityFeePerGas,\n maxFeePerGas,\n originalGasEstimate,\n userEditedGasLimit,\n userFeeLevel,\n }: {\n defaultGasEstimates?: string;\n estimateUsed?: string;\n estimateSuggested?: string;\n gas?: string;\n gasLimit?: string;\n gasPrice?: string;\n maxPriorityFeePerGas?: string;\n maxFeePerGas?: string;\n originalGasEstimate?: string;\n userEditedGasLimit?: boolean;\n userFeeLevel?: string;\n },\n ): TransactionMeta {\n const transactionMeta = this.getTransaction(transactionId);\n\n if (!transactionMeta) {\n throw new Error(\n `Cannot update transaction as no transaction metadata found`,\n );\n }\n\n validateIfTransactionUnapproved(\n transactionMeta,\n 'updateTransactionGasFees',\n );\n\n let transactionGasFees = {\n txParams: {\n gas,\n gasLimit,\n gasPrice,\n maxPriorityFeePerGas,\n maxFeePerGas,\n },\n defaultGasEstimates,\n estimateUsed,\n estimateSuggested,\n originalGasEstimate,\n userEditedGasLimit,\n userFeeLevel,\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n\n // only update what is defined\n transactionGasFees.txParams = pickBy(transactionGasFees.txParams);\n transactionGasFees = pickBy(transactionGasFees);\n\n // merge updated gas values with existing transaction meta\n const updatedMeta = merge({}, transactionMeta, transactionGasFees);\n\n this.updateTransaction(\n updatedMeta,\n `${controllerName}:updateTransactionGasFees - gas values updated`,\n );\n\n return this.getTransaction(transactionId) as TransactionMeta;\n }\n\n /**\n * Update the previous gas values of a transaction.\n *\n * @param transactionId - The ID of the transaction to update.\n * @param previousGas - Previous gas values to update.\n * @param previousGas.gasLimit - Maxmimum number of units of gas to use for this transaction.\n * @param previousGas.maxFeePerGas - Maximum amount per gas to pay for the transaction, including the priority fee.\n * @param previousGas.maxPriorityFeePerGas - Maximum amount per gas to give to validator as incentive.\n * @returns The updated transactionMeta.\n */\n updatePreviousGasParams(\n transactionId: string,\n {\n gasLimit,\n maxFeePerGas,\n maxPriorityFeePerGas,\n }: {\n gasLimit?: string;\n maxFeePerGas?: string;\n maxPriorityFeePerGas?: string;\n },\n ): TransactionMeta {\n const transactionMeta = this.getTransaction(transactionId);\n\n if (!transactionMeta) {\n throw new Error(\n `Cannot update transaction as no transaction metadata found`,\n );\n }\n\n validateIfTransactionUnapproved(transactionMeta, 'updatePreviousGasParams');\n\n const transactionPreviousGas = {\n previousGas: {\n gasLimit,\n maxFeePerGas,\n maxPriorityFeePerGas,\n },\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n\n // only update what is defined\n transactionPreviousGas.previousGas = pickBy(\n transactionPreviousGas.previousGas,\n );\n\n // merge updated previous gas values with existing transaction meta\n const updatedMeta = merge({}, transactionMeta, transactionPreviousGas);\n\n this.updateTransaction(\n updatedMeta,\n `${controllerName}:updatePreviousGasParams - Previous gas values updated`,\n );\n\n return this.getTransaction(transactionId) as TransactionMeta;\n }\n\n async getNonceLock(\n address: string,\n networkClientId?: NetworkClientId,\n ): Promise {\n return this.#multichainTrackingHelper.getNonceLock(\n address,\n networkClientId,\n );\n }\n\n /**\n * Updates the editable parameters of a transaction.\n *\n * @param txId - The ID of the transaction to update.\n * @param params - The editable parameters to update.\n * @param params.data - Data to pass with the transaction.\n * @param params.gas - Maximum number of units of gas to use for the transaction.\n * @param params.gasPrice - Price per gas for legacy transactions.\n * @param params.from - Address to send the transaction from.\n * @param params.to - Address to send the transaction to.\n * @param params.value - Value associated with the transaction.\n * @returns The updated transaction metadata.\n */\n async updateEditableParams(\n txId: string,\n {\n data,\n gas,\n gasPrice,\n from,\n to,\n value,\n }: {\n data?: string;\n gas?: string;\n gasPrice?: string;\n from?: string;\n to?: string;\n value?: string;\n },\n ) {\n const transactionMeta = this.getTransaction(txId);\n if (!transactionMeta) {\n throw new Error(\n `Cannot update editable params as no transaction metadata found`,\n );\n }\n\n validateIfTransactionUnapproved(transactionMeta, 'updateEditableParams');\n\n const editableParams = {\n txParams: {\n data,\n from,\n to,\n value,\n gas,\n gasPrice,\n },\n } as Partial;\n\n editableParams.txParams = pickBy(\n editableParams.txParams,\n ) as TransactionParams;\n\n const updatedTransaction = merge({}, transactionMeta, editableParams);\n const provider = this.#multichainTrackingHelper.getProvider({\n chainId: transactionMeta.chainId,\n networkClientId: transactionMeta.networkClientId,\n });\n const ethQuery = new EthQuery(provider);\n const { type } = await determineTransactionType(\n updatedTransaction.txParams,\n ethQuery,\n );\n updatedTransaction.type = type;\n\n await updateTransactionLayer1GasFee({\n layer1GasFeeFlows: this.layer1GasFeeFlows,\n provider,\n transactionMeta: updatedTransaction,\n });\n\n this.updateTransaction(\n updatedTransaction,\n `Update Editable Params for ${txId}`,\n );\n return this.getTransaction(txId);\n }\n\n /**\n * Signs and returns the raw transaction data for provided transaction params list.\n *\n * @param listOfTxParams - The list of transaction params to approve.\n * @param opts - Options bag.\n * @param opts.hasNonce - Whether the transactions already have a nonce.\n * @returns The raw transactions.\n */\n async approveTransactionsWithSameNonce(\n listOfTxParams: (TransactionParams & { chainId: Hex })[] = [],\n { hasNonce }: { hasNonce?: boolean } = {},\n ): Promise {\n log('Approving transactions with same nonce', {\n transactions: listOfTxParams,\n });\n\n if (listOfTxParams.length === 0) {\n return '';\n }\n\n const initialTx = listOfTxParams[0];\n const common = this.getCommonConfiguration(initialTx.chainId);\n\n // We need to ensure we get the nonce using the the NonceTracker on the chain matching\n // the txParams. In this context we only have chainId available to us, but the\n // NonceTrackers are keyed by networkClientId. To workaround this, we attempt to find\n // a networkClientId that matches the chainId. As a fallback, the globally selected\n // network's NonceTracker will be used instead.\n let networkClientId: NetworkClientId | undefined;\n try {\n networkClientId = this.messagingSystem.call(\n `NetworkController:findNetworkClientIdByChainId`,\n initialTx.chainId,\n );\n } catch (err) {\n log('failed to find networkClientId from chainId', err);\n }\n\n const initialTxAsEthTx = TransactionFactory.fromTxData(initialTx, {\n common,\n });\n const initialTxAsSerializedHex = bufferToHex(initialTxAsEthTx.serialize());\n\n if (this.approvingTransactionIds.has(initialTxAsSerializedHex)) {\n return '';\n }\n this.approvingTransactionIds.add(initialTxAsSerializedHex);\n\n let rawTransactions, nonceLock;\n try {\n // TODO: we should add a check to verify that all transactions have the same from address\n const fromAddress = initialTx.from;\n const requiresNonce = hasNonce !== true;\n\n nonceLock = requiresNonce\n ? await this.getNonceLock(fromAddress, networkClientId)\n : undefined;\n\n const nonce = nonceLock\n ? add0x(nonceLock.nextNonce.toString(16))\n : initialTx.nonce;\n\n if (nonceLock) {\n log('Using nonce from nonce tracker', nonce, nonceLock.nonceDetails);\n }\n\n rawTransactions = await Promise.all(\n listOfTxParams.map((txParams) => {\n txParams.nonce = nonce;\n return this.signExternalTransaction(txParams.chainId, txParams);\n }),\n );\n } catch (err) {\n log('Error while signing transactions with same nonce', err);\n // Must set transaction to submitted/failed before releasing lock\n // continue with error chain\n throw err;\n } finally {\n nonceLock?.releaseLock();\n this.approvingTransactionIds.delete(initialTxAsSerializedHex);\n }\n return rawTransactions;\n }\n\n /**\n * Update a custodial transaction.\n *\n * @param transactionId - The ID of the transaction to update.\n * @param options - The custodial transaction options to update.\n * @param options.errorMessage - The error message to be assigned in case transaction status update to failed.\n * @param options.hash - The new hash value to be assigned.\n * @param options.status - The new status value to be assigned.\n */\n updateCustodialTransaction(\n transactionId: string,\n {\n errorMessage,\n hash,\n status,\n }: {\n errorMessage?: string;\n hash?: string;\n status?: TransactionStatus;\n },\n ) {\n const transactionMeta = this.getTransaction(transactionId);\n\n if (!transactionMeta) {\n throw new Error(\n `Cannot update custodial transaction as no transaction metadata found`,\n );\n }\n\n if (!transactionMeta.custodyId) {\n throw new Error('Transaction must be a custodian transaction');\n }\n\n if (\n status &&\n ![\n TransactionStatus.submitted,\n TransactionStatus.signed,\n TransactionStatus.failed,\n ].includes(status)\n ) {\n throw new Error(\n `Cannot update custodial transaction with status: ${status}`,\n );\n }\n\n const updatedTransactionMeta = merge(\n {},\n transactionMeta,\n pickBy({ hash, status }),\n ) as TransactionMeta;\n\n if (updatedTransactionMeta.status === TransactionStatus.submitted) {\n updatedTransactionMeta.submittedTime = new Date().getTime();\n }\n\n if (updatedTransactionMeta.status === TransactionStatus.failed) {\n updatedTransactionMeta.error = normalizeTxError(new Error(errorMessage));\n }\n\n this.updateTransaction(\n updatedTransactionMeta,\n `${controllerName}:updateCustodialTransaction - Custodial transaction updated`,\n );\n\n if (\n [TransactionStatus.submitted, TransactionStatus.failed].includes(\n status as TransactionStatus,\n )\n ) {\n this.messagingSystem.publish(\n `${controllerName}:transactionFinished`,\n updatedTransactionMeta,\n );\n this.#internalEvents.emit(\n `${updatedTransactionMeta.id}:finished`,\n updatedTransactionMeta,\n );\n }\n }\n\n /**\n * Search transaction metadata for matching entries.\n *\n * @param opts - Options bag.\n * @param opts.searchCriteria - An object containing values or functions for transaction properties to filter transactions with.\n * @param opts.initialList - The transactions to search. Defaults to the current state.\n * @param opts.filterToCurrentNetwork - Whether to filter the results to the current network. Defaults to true.\n * @param opts.limit - The maximum number of transactions to return. No limit by default.\n * @returns An array of transactions matching the provided options.\n */\n getTransactions({\n searchCriteria = {},\n initialList,\n filterToCurrentNetwork = true,\n limit,\n }: {\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n searchCriteria?: any;\n initialList?: TransactionMeta[];\n filterToCurrentNetwork?: boolean;\n limit?: number;\n } = {}): TransactionMeta[] {\n const chainId = this.getChainId();\n // searchCriteria is an object that might have values that aren't predicate\n // methods. When providing any other value type (string, number, etc), we\n // consider this shorthand for \"check the value at key for strict equality\n // with the provided value\". To conform this object to be only methods, we\n // mapValues (lodash) such that every value on the object is a method that\n // returns a boolean.\n const predicateMethods = mapValues(searchCriteria, (predicate) => {\n return typeof predicate === 'function'\n ? predicate\n : // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (v: any) => v === predicate;\n });\n\n const transactionsToFilter = initialList ?? this.state.transactions;\n\n // Combine sortBy and pickBy to transform our state object into an array of\n // matching transactions that are sorted by time.\n const filteredTransactions = sortBy(\n pickBy(transactionsToFilter, (transaction) => {\n if (filterToCurrentNetwork && transaction.chainId !== chainId) {\n return false;\n }\n // iterate over the predicateMethods keys to check if the transaction\n // matches the searchCriteria\n for (const [key, predicate] of Object.entries(predicateMethods)) {\n // We return false early as soon as we know that one of the specified\n // search criteria do not match the transaction. This prevents\n // needlessly checking all criteria when we already know the criteria\n // are not fully satisfied. We check both txParams and the base\n // object as predicate keys can be either.\n if (key in transaction.txParams) {\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (predicate((transaction.txParams as any)[key]) === false) {\n return false;\n }\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } else if (predicate((transaction as any)[key]) === false) {\n return false;\n }\n }\n\n return true;\n }),\n 'time',\n );\n if (limit !== undefined) {\n // We need to have all transactions of a given nonce in order to display\n // necessary details in the UI. We use the size of this set to determine\n // whether we have reached the limit provided, thus ensuring that all\n // transactions of nonces we include will be sent to the UI.\n const nonces = new Set();\n const txs = [];\n // By default, the transaction list we filter from is sorted by time ASC.\n // To ensure that filtered results prefers the newest transactions we\n // iterate from right to left, inserting transactions into front of a new\n // array. The original order is preserved, but we ensure that newest txs\n // are preferred.\n for (let i = filteredTransactions.length - 1; i > -1; i--) {\n const txMeta = filteredTransactions[i];\n const { nonce } = txMeta.txParams;\n if (!nonces.has(nonce)) {\n if (nonces.size < limit) {\n nonces.add(nonce);\n } else {\n continue;\n }\n }\n // Push transaction into the beginning of our array to ensure the\n // original order is preserved.\n txs.unshift(txMeta);\n }\n return txs;\n }\n return filteredTransactions;\n }\n\n async estimateGasFee({\n transactionParams,\n chainId,\n networkClientId: requestNetworkClientId,\n }: {\n transactionParams: TransactionParams;\n chainId?: Hex;\n networkClientId?: NetworkClientId;\n }): Promise {\n const networkClientId = this.#getNetworkClientId({\n networkClientId: requestNetworkClientId,\n chainId,\n });\n\n const transactionMeta = {\n txParams: transactionParams,\n chainId,\n networkClientId,\n } as TransactionMeta;\n\n // Guaranteed as the default gas fee flow matches all transactions.\n const gasFeeFlow = getGasFeeFlow(\n transactionMeta,\n this.gasFeeFlows,\n ) as GasFeeFlow;\n\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId,\n chainId,\n });\n\n const gasFeeControllerData = await this.getGasFeeEstimates({\n networkClientId,\n });\n\n return gasFeeFlow.getGasFees({\n ethQuery,\n gasFeeControllerData,\n transactionMeta,\n });\n }\n\n /**\n * Determine the layer 1 gas fee for the given transaction parameters.\n *\n * @param request - The request object.\n * @param request.transactionParams - The transaction parameters to estimate the layer 1 gas fee for.\n * @param request.chainId - The ID of the chain where the transaction will be executed.\n * @param request.networkClientId - The ID of a specific network client to process the transaction.\n */\n async getLayer1GasFee({\n transactionParams,\n chainId,\n networkClientId,\n }: {\n transactionParams: TransactionParams;\n chainId?: Hex;\n networkClientId?: NetworkClientId;\n }): Promise {\n const provider = this.#multichainTrackingHelper.getProvider({\n networkClientId,\n chainId,\n });\n\n return await getTransactionLayer1GasFee({\n layer1GasFeeFlows: this.layer1GasFeeFlows,\n provider,\n transactionMeta: {\n txParams: transactionParams,\n chainId,\n } as TransactionMeta,\n });\n }\n\n private async signExternalTransaction(\n chainId: Hex,\n transactionParams: TransactionParams,\n ): Promise {\n if (!this.sign) {\n throw new Error('No sign method defined.');\n }\n\n const normalizedTransactionParams =\n normalizeTransactionParams(transactionParams);\n const type = isEIP1559Transaction(normalizedTransactionParams)\n ? TransactionEnvelopeType.feeMarket\n : TransactionEnvelopeType.legacy;\n const updatedTransactionParams = {\n ...normalizedTransactionParams,\n type,\n gasLimit: normalizedTransactionParams.gas,\n chainId,\n };\n\n const { from } = updatedTransactionParams;\n const common = this.getCommonConfiguration(chainId);\n const unsignedTransaction = TransactionFactory.fromTxData(\n updatedTransactionParams,\n { common },\n );\n const signedTransaction = await this.sign(unsignedTransaction, from);\n\n const rawTransaction = bufferToHex(signedTransaction.serialize());\n return rawTransaction;\n }\n\n /**\n * Removes unapproved transactions from state.\n */\n clearUnapprovedTransactions() {\n const transactions = this.state.transactions.filter(\n ({ status }) => status !== TransactionStatus.unapproved,\n );\n this.update((state) => {\n state.transactions = this.trimTransactionsForState(transactions);\n });\n }\n\n /**\n * Stop the signing process for a specific transaction.\n * Throws an error causing the transaction status to be set to failed.\n * @param transactionId - The ID of the transaction to stop signing.\n */\n abortTransactionSigning(transactionId: string) {\n const transactionMeta = this.getTransaction(transactionId);\n\n if (!transactionMeta) {\n throw new Error(`Cannot abort signing as no transaction metadata found`);\n }\n\n const abortCallback = this.signAbortCallbacks.get(transactionId);\n\n if (!abortCallback) {\n throw new Error(\n `Cannot abort signing as transaction is not waiting for signing`,\n );\n }\n\n abortCallback();\n\n this.signAbortCallbacks.delete(transactionId);\n }\n\n private addMetadata(transactionMeta: TransactionMeta) {\n this.update((state) => {\n state.transactions = this.trimTransactionsForState([\n ...state.transactions,\n transactionMeta,\n ]);\n });\n }\n\n private async updateGasProperties(transactionMeta: TransactionMeta) {\n const isEIP1559Compatible =\n (await this.getEIP1559Compatibility(transactionMeta.networkClientId)) &&\n transactionMeta.txParams.type !== TransactionEnvelopeType.legacy;\n\n const { networkClientId, chainId } = transactionMeta;\n\n const isCustomNetwork = this.#isCustomNetwork(networkClientId);\n\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId,\n chainId,\n });\n\n const provider = this.#multichainTrackingHelper.getProvider({\n networkClientId,\n chainId,\n });\n\n await updateGas({\n ethQuery,\n chainId,\n isCustomNetwork,\n txMeta: transactionMeta,\n });\n\n await updateGasFees({\n eip1559: isEIP1559Compatible,\n ethQuery,\n gasFeeFlows: this.gasFeeFlows,\n getGasFeeEstimates: this.getGasFeeEstimates,\n getSavedGasFees: this.getSavedGasFees.bind(this),\n txMeta: transactionMeta,\n });\n\n await updateTransactionLayer1GasFee({\n layer1GasFeeFlows: this.layer1GasFeeFlows,\n provider,\n transactionMeta,\n });\n }\n\n private onBootCleanup() {\n this.clearUnapprovedTransactions();\n this.failIncompleteTransactions();\n }\n\n private failIncompleteTransactions() {\n const incompleteTransactions = this.state.transactions.filter(\n (transaction) =>\n [TransactionStatus.approved, TransactionStatus.signed].includes(\n transaction.status,\n ),\n );\n\n for (const transactionMeta of incompleteTransactions) {\n this.failTransaction(\n transactionMeta,\n new Error('Transaction incomplete at startup'),\n );\n }\n }\n\n private async processApproval(\n transactionMeta: TransactionMeta,\n {\n isExisting = false,\n requireApproval,\n shouldShowRequest = true,\n actionId,\n }: {\n isExisting?: boolean;\n requireApproval?: boolean | undefined;\n shouldShowRequest?: boolean;\n actionId?: string;\n },\n ): Promise {\n const transactionId = transactionMeta.id;\n let resultCallbacks: AcceptResultCallbacks | undefined;\n const { meta, isCompleted } = this.isTransactionCompleted(transactionId);\n const finishedPromise = isCompleted\n ? Promise.resolve(meta)\n : this.waitForTransactionFinished(transactionId);\n\n if (meta && !isExisting && !isCompleted) {\n try {\n if (requireApproval !== false) {\n const acceptResult = await this.requestApproval(transactionMeta, {\n shouldShowRequest,\n });\n resultCallbacks = acceptResult.resultCallbacks;\n\n const approvalValue = acceptResult.value as\n | {\n txMeta?: TransactionMeta;\n }\n | undefined;\n\n const updatedTransaction = approvalValue?.txMeta;\n\n if (updatedTransaction) {\n log('Updating transaction with approval data', {\n customNonce: updatedTransaction.customNonceValue,\n params: updatedTransaction.txParams,\n });\n\n this.updateTransaction(\n updatedTransaction,\n 'TransactionController#processApproval - Updated with approval data',\n );\n }\n }\n\n const { isCompleted: isTxCompleted } =\n this.isTransactionCompleted(transactionId);\n\n if (!isTxCompleted) {\n const approvalResult = await this.approveTransaction(transactionId);\n if (\n approvalResult === ApprovalState.SkippedViaBeforePublishHook &&\n resultCallbacks\n ) {\n resultCallbacks.success();\n }\n const updatedTransactionMeta = this.getTransaction(\n transactionId,\n ) as TransactionMeta;\n this.messagingSystem.publish(\n `${controllerName}:transactionApproved`,\n {\n transactionMeta: updatedTransactionMeta,\n actionId,\n },\n );\n }\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n const { isCompleted: isTxCompleted } =\n this.isTransactionCompleted(transactionId);\n if (!isTxCompleted) {\n if (error?.code === errorCodes.provider.userRejectedRequest) {\n this.cancelTransaction(transactionId, actionId);\n\n throw providerErrors.userRejectedRequest(\n 'MetaMask Tx Signature: User denied transaction signature.',\n );\n } else {\n this.failTransaction(meta, error, actionId);\n }\n }\n }\n }\n\n const finalMeta = await finishedPromise;\n\n switch (finalMeta?.status) {\n case TransactionStatus.failed:\n resultCallbacks?.error(finalMeta.error);\n throw rpcErrors.internal(finalMeta.error.message);\n\n case TransactionStatus.submitted:\n resultCallbacks?.success();\n return finalMeta.hash as string;\n\n default:\n const internalError = rpcErrors.internal(\n `MetaMask Tx Signature: Unknown problem: ${JSON.stringify(\n finalMeta || transactionId,\n )}`,\n );\n\n resultCallbacks?.error(internalError);\n throw internalError;\n }\n }\n\n /**\n * Approves a transaction and updates it's status in state. If this is not a\n * retry transaction, a nonce will be generated. The transaction is signed\n * using the sign configuration property, then published to the blockchain.\n * A `:finished` hub event is fired after success or failure.\n *\n * @param transactionId - The ID of the transaction to approve.\n */\n private async approveTransaction(transactionId: string) {\n const cleanupTasks = new Array<() => void>();\n cleanupTasks.push(await this.mutex.acquire());\n\n let transactionMeta = this.getTransactionOrThrow(transactionId);\n\n try {\n if (!this.sign) {\n this.failTransaction(\n transactionMeta,\n new Error('No sign method defined.'),\n );\n return ApprovalState.NotApproved;\n } else if (!transactionMeta.chainId) {\n this.failTransaction(transactionMeta, new Error('No chainId defined.'));\n return ApprovalState.NotApproved;\n }\n\n if (this.approvingTransactionIds.has(transactionId)) {\n log('Skipping approval as signing in progress', transactionId);\n return ApprovalState.NotApproved;\n }\n this.approvingTransactionIds.add(transactionId);\n cleanupTasks.push(() =>\n this.approvingTransactionIds.delete(transactionId),\n );\n\n const [nonce, releaseNonce] = await getNextNonce(\n transactionMeta,\n (address: string) =>\n this.#multichainTrackingHelper.getNonceLock(\n address,\n transactionMeta.networkClientId,\n ),\n );\n\n // must set transaction to submitted/failed before releasing lock\n releaseNonce && cleanupTasks.push(releaseNonce);\n\n transactionMeta = this.#updateTransactionInternal(\n {\n transactionId,\n note: 'TransactionController#approveTransaction - Transaction approved',\n },\n (draftTxMeta) => {\n const { txParams, chainId } = draftTxMeta;\n\n draftTxMeta.status = TransactionStatus.approved;\n draftTxMeta.txParams = {\n ...txParams,\n nonce,\n chainId,\n gasLimit: txParams.gas,\n ...(isEIP1559Transaction(txParams) && {\n type: TransactionEnvelopeType.feeMarket,\n }),\n };\n },\n );\n\n this.onTransactionStatusChange(transactionMeta);\n\n const rawTx = await this.signTransaction(\n transactionMeta,\n transactionMeta.txParams,\n );\n\n if (!this.beforePublish(transactionMeta)) {\n log('Skipping publishing transaction based on hook');\n this.messagingSystem.publish(\n `${controllerName}:transactionPublishingSkipped`,\n transactionMeta,\n );\n return ApprovalState.SkippedViaBeforePublishHook;\n }\n\n if (!rawTx) {\n return ApprovalState.NotApproved;\n }\n\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId: transactionMeta.networkClientId,\n chainId: transactionMeta.chainId,\n });\n\n let preTxBalance: string | undefined;\n const shouldUpdatePreTxBalance =\n transactionMeta.type === TransactionType.swap;\n\n if (shouldUpdatePreTxBalance) {\n log('Determining pre-transaction balance');\n\n preTxBalance = await query(ethQuery, 'getBalance', [\n transactionMeta.txParams.from,\n ]);\n }\n\n log('Publishing transaction', transactionMeta.txParams);\n\n let { transactionHash: hash } = await this.publish(\n transactionMeta,\n rawTx,\n );\n\n if (hash === undefined) {\n hash = await this.publishTransaction(ethQuery, rawTx);\n }\n\n log('Publish successful', hash);\n\n transactionMeta = this.#updateTransactionInternal(\n {\n transactionId,\n note: 'TransactionController#approveTransaction - Transaction submitted',\n },\n (draftTxMeta) => {\n draftTxMeta.hash = hash;\n draftTxMeta.status = TransactionStatus.submitted;\n draftTxMeta.submittedTime = new Date().getTime();\n if (shouldUpdatePreTxBalance) {\n draftTxMeta.preTxBalance = preTxBalance;\n log('Updated pre-transaction balance', preTxBalance);\n }\n },\n );\n\n this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {\n transactionMeta,\n });\n\n this.messagingSystem.publish(\n `${controllerName}:transactionFinished`,\n transactionMeta,\n );\n this.#internalEvents.emit(`${transactionId}:finished`, transactionMeta);\n\n this.onTransactionStatusChange(transactionMeta);\n return ApprovalState.Approved;\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n this.failTransaction(transactionMeta, error);\n return ApprovalState.NotApproved;\n } finally {\n cleanupTasks.forEach((task) => task());\n }\n }\n\n private async publishTransaction(\n ethQuery: EthQuery,\n rawTransaction: string,\n ): Promise {\n return await query(ethQuery, 'sendRawTransaction', [rawTransaction]);\n }\n\n /**\n * Cancels a transaction based on its ID by setting its status to \"rejected\"\n * and emitting a `:finished` hub event.\n *\n * @param transactionId - The ID of the transaction to cancel.\n * @param actionId - The actionId passed from UI\n */\n private cancelTransaction(transactionId: string, actionId?: string) {\n const transactionMeta = this.state.transactions.find(\n ({ id }) => id === transactionId,\n );\n if (!transactionMeta) {\n return;\n }\n this.update((state) => {\n const transactions = state.transactions.filter(\n ({ id }) => id !== transactionId,\n );\n state.transactions = this.trimTransactionsForState(transactions);\n });\n const updatedTransactionMeta = {\n ...transactionMeta,\n status: TransactionStatus.rejected as const,\n };\n this.messagingSystem.publish(\n `${controllerName}:transactionFinished`,\n updatedTransactionMeta,\n );\n this.#internalEvents.emit(\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n `${transactionMeta.id}:finished`,\n updatedTransactionMeta,\n );\n this.messagingSystem.publish(`${controllerName}:transactionRejected`, {\n transactionMeta: updatedTransactionMeta,\n actionId,\n });\n this.onTransactionStatusChange(updatedTransactionMeta);\n }\n\n /**\n * Trim the amount of transactions that are set on the state. Checks\n * if the length of the tx history is longer then desired persistence\n * limit and then if it is removes the oldest confirmed or rejected tx.\n * Pending or unapproved transactions will not be removed by this\n * operation. For safety of presenting a fully functional transaction UI\n * representation, this function will not break apart transactions with the\n * same nonce, created on the same day, per network. Not accounting for\n * transactions of the same nonce, same day and network combo can result in\n * confusing or broken experiences in the UI.\n *\n * @param transactions - The transactions to be applied to the state.\n * @returns The trimmed list of transactions.\n */\n private trimTransactionsForState(\n transactions: TransactionMeta[],\n ): TransactionMeta[] {\n const nonceNetworkSet = new Set();\n\n const txsToKeep = [...transactions]\n .sort((a, b) => (a.time > b.time ? -1 : 1)) // Descending time order\n .filter((tx) => {\n const { chainId, status, txParams, time } = tx;\n\n if (txParams) {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n const key = `${String(txParams.nonce)}-${convertHexToDecimal(\n chainId,\n )}-${new Date(time).toDateString()}`;\n\n if (nonceNetworkSet.has(key)) {\n return true;\n } else if (\n nonceNetworkSet.size < this.#transactionHistoryLimit ||\n !this.isFinalState(status)\n ) {\n nonceNetworkSet.add(key);\n return true;\n }\n }\n\n return false;\n });\n\n txsToKeep.reverse(); // Ascending time order\n return txsToKeep;\n }\n\n /**\n * Determines if the transaction is in a final state.\n *\n * @param status - The transaction status.\n * @returns Whether the transaction is in a final state.\n */\n private isFinalState(status: TransactionStatus): boolean {\n return (\n status === TransactionStatus.rejected ||\n status === TransactionStatus.confirmed ||\n status === TransactionStatus.failed\n );\n }\n\n /**\n * Whether the transaction has at least completed all local processing.\n *\n * @param status - The transaction status.\n * @returns Whether the transaction is in a final state.\n */\n private isLocalFinalState(status: TransactionStatus): boolean {\n return [\n TransactionStatus.confirmed,\n TransactionStatus.failed,\n TransactionStatus.rejected,\n TransactionStatus.submitted,\n ].includes(status);\n }\n\n private async requestApproval(\n txMeta: TransactionMeta,\n { shouldShowRequest }: { shouldShowRequest: boolean },\n ): Promise {\n const id = this.getApprovalId(txMeta);\n const { origin } = txMeta;\n const type = ApprovalType.Transaction;\n const requestData = { txId: txMeta.id };\n\n return (await this.messagingSystem.call(\n 'ApprovalController:addRequest',\n {\n id,\n origin: origin || ORIGIN_METAMASK,\n type,\n requestData,\n expectsResult: true,\n },\n shouldShowRequest,\n )) as Promise;\n }\n\n private getTransaction(\n transactionId: string,\n ): Readonly | undefined {\n const { transactions } = this.state;\n return transactions.find(({ id }) => id === transactionId);\n }\n\n private getTransactionOrThrow(\n transactionId: string,\n errorMessagePrefix = 'TransactionController',\n ): Readonly {\n const txMeta = this.getTransaction(transactionId);\n if (!txMeta) {\n throw new Error(\n `${errorMessagePrefix}: No transaction found with id ${transactionId}`,\n );\n }\n return txMeta;\n }\n\n private getApprovalId(txMeta: TransactionMeta) {\n return String(txMeta.id);\n }\n\n private isTransactionCompleted(transactionId: string): {\n meta?: TransactionMeta;\n isCompleted: boolean;\n } {\n const transaction = this.getTransaction(transactionId);\n\n if (!transaction) {\n return { meta: undefined, isCompleted: false };\n }\n\n const isCompleted = this.isLocalFinalState(transaction.status);\n\n return { meta: transaction, isCompleted };\n }\n\n private getChainId(networkClientId?: NetworkClientId): Hex {\n const globalChainId = this.#getGlobalChainId();\n const globalNetworkClientId = this.#getGlobalNetworkClientId();\n\n if (!networkClientId || networkClientId === globalNetworkClientId) {\n return globalChainId;\n }\n\n return this.messagingSystem.call(\n `NetworkController:getNetworkClientById`,\n networkClientId,\n ).configuration.chainId;\n }\n\n private prepareUnsignedEthTx(\n chainId: Hex,\n txParams: TransactionParams,\n ): TypedTransaction {\n return TransactionFactory.fromTxData(txParams, {\n freeze: false,\n common: this.getCommonConfiguration(chainId),\n });\n }\n\n /**\n * `@ethereumjs/tx` uses `@ethereumjs/common` as a configuration tool for\n * specifying which chain, network, hardfork and EIPs to support for\n * a transaction. By referencing this configuration, and analyzing the fields\n * specified in txParams, @ethereumjs/tx is able to determine which EIP-2718\n * transaction type to use.\n *\n * @param chainId - The chainId to use for the configuration.\n * @returns common configuration object\n */\n private getCommonConfiguration(chainId: Hex): Common {\n const customChainParams: Partial = {\n chainId: parseInt(chainId, 16),\n defaultHardfork: HARDFORK,\n };\n\n return Common.custom(customChainParams);\n }\n\n private onIncomingTransactions({\n added,\n updated,\n }: {\n added: TransactionMeta[];\n updated: TransactionMeta[];\n }) {\n this.update((state) => {\n const { transactions: currentTransactions } = state;\n const updatedTransactions = [\n ...added,\n ...currentTransactions.map((originalTransaction) => {\n const updatedTransaction = updated.find(\n ({ hash }) => hash === originalTransaction.hash,\n );\n\n return updatedTransaction ?? originalTransaction;\n }),\n ];\n\n state.transactions = this.trimTransactionsForState(updatedTransactions);\n });\n }\n\n private onUpdatedLastFetchedBlockNumbers({\n lastFetchedBlockNumbers,\n blockNumber,\n }: {\n lastFetchedBlockNumbers: {\n [key: string]: number;\n };\n blockNumber: number;\n }) {\n this.update((state) => {\n state.lastFetchedBlockNumbers = lastFetchedBlockNumbers;\n });\n this.messagingSystem.publish(\n `${controllerName}:incomingTransactionBlockReceived`,\n blockNumber,\n );\n }\n\n private generateDappSuggestedGasFees(\n txParams: TransactionParams,\n origin?: string,\n ): DappSuggestedGasFees | undefined {\n if (!origin || origin === ORIGIN_METAMASK) {\n return undefined;\n }\n\n const { gasPrice, maxFeePerGas, maxPriorityFeePerGas, gas } = txParams;\n\n if (\n gasPrice === undefined &&\n maxFeePerGas === undefined &&\n maxPriorityFeePerGas === undefined &&\n gas === undefined\n ) {\n return undefined;\n }\n\n const dappSuggestedGasFees: DappSuggestedGasFees = {};\n\n if (gasPrice !== undefined) {\n dappSuggestedGasFees.gasPrice = gasPrice;\n } else if (\n maxFeePerGas !== undefined ||\n maxPriorityFeePerGas !== undefined\n ) {\n dappSuggestedGasFees.maxFeePerGas = maxFeePerGas;\n dappSuggestedGasFees.maxPriorityFeePerGas = maxPriorityFeePerGas;\n }\n\n if (gas !== undefined) {\n dappSuggestedGasFees.gas = gas;\n }\n\n return dappSuggestedGasFees;\n }\n\n /**\n * Validates and adds external provided transaction to state.\n *\n * @param transactionMeta - Nominated external transaction to be added to state.\n * @returns The new transaction.\n */\n private addExternalTransaction(transactionMeta: TransactionMeta) {\n const { chainId } = transactionMeta;\n const { transactions } = this.state;\n const fromAddress = transactionMeta?.txParams?.from;\n const sameFromAndNetworkTransactions = transactions.filter(\n (transaction) =>\n transaction.txParams.from === fromAddress &&\n transaction.chainId === chainId,\n );\n const confirmedTxs = sameFromAndNetworkTransactions.filter(\n (transaction) => transaction.status === TransactionStatus.confirmed,\n );\n const pendingTxs = sameFromAndNetworkTransactions.filter(\n (transaction) => transaction.status === TransactionStatus.submitted,\n );\n\n validateConfirmedExternalTransaction(\n transactionMeta,\n confirmedTxs,\n pendingTxs,\n );\n\n // Make sure provided external transaction has non empty history array\n const newTransactionMeta =\n (transactionMeta.history ?? []).length === 0 && !this.isHistoryDisabled\n ? addInitialHistorySnapshot(transactionMeta)\n : transactionMeta;\n\n this.update((state) => {\n state.transactions = this.trimTransactionsForState([\n ...state.transactions,\n newTransactionMeta,\n ]);\n });\n\n return newTransactionMeta;\n }\n\n /**\n * Sets other txMeta statuses to dropped if the txMeta that has been confirmed has other transactions\n * in the transactions have the same nonce.\n *\n * @param transactionId - Used to identify original transaction.\n */\n private markNonceDuplicatesDropped(transactionId: string) {\n const transactionMeta = this.getTransaction(transactionId);\n if (!transactionMeta) {\n return;\n }\n const nonce = transactionMeta.txParams?.nonce;\n const from = transactionMeta.txParams?.from;\n const { chainId } = transactionMeta;\n\n const sameNonceTransactions = this.state.transactions.filter(\n (transaction) =>\n transaction.id !== transactionId &&\n transaction.txParams.from === from &&\n transaction.txParams.nonce === nonce &&\n transaction.chainId === chainId &&\n transaction.type !== TransactionType.incoming,\n );\n const sameNonceTransactionIds = sameNonceTransactions.map(\n (transaction) => transaction.id,\n );\n\n if (sameNonceTransactions.length === 0) {\n return;\n }\n\n this.update((state) => {\n for (const transaction of state.transactions) {\n if (sameNonceTransactionIds.includes(transaction.id)) {\n transaction.replacedBy = transactionMeta?.hash;\n transaction.replacedById = transactionMeta?.id;\n }\n }\n });\n\n for (const transaction of this.state.transactions) {\n if (\n sameNonceTransactionIds.includes(transaction.id) &&\n transaction.status !== TransactionStatus.failed\n ) {\n this.setTransactionStatusDropped(transaction);\n }\n }\n }\n\n /**\n * Method to set transaction status to dropped.\n *\n * @param transactionMeta - TransactionMeta of transaction to be marked as dropped.\n */\n private setTransactionStatusDropped(transactionMeta: TransactionMeta) {\n const updatedTransactionMeta = {\n ...transactionMeta,\n status: TransactionStatus.dropped as const,\n };\n this.messagingSystem.publish(`${controllerName}:transactionDropped`, {\n transactionMeta: updatedTransactionMeta,\n });\n this.updateTransaction(\n updatedTransactionMeta,\n 'TransactionController#setTransactionStatusDropped - Transaction dropped',\n );\n this.onTransactionStatusChange(updatedTransactionMeta);\n }\n\n /**\n * Get transaction with provided actionId.\n *\n * @param actionId - Unique ID to prevent duplicate requests\n * @returns the filtered transaction\n */\n private getTransactionWithActionId(actionId?: string) {\n return this.state.transactions.find(\n (transaction) => actionId && transaction.actionId === actionId,\n );\n }\n\n private async waitForTransactionFinished(\n transactionId: string,\n ): Promise {\n return new Promise((resolve) => {\n this.#internalEvents.once(`${transactionId}:finished`, (txMeta) => {\n resolve(txMeta);\n });\n });\n }\n\n /**\n * Updates the r, s, and v properties of a TransactionMeta object\n * with values from a signed transaction.\n *\n * @param transactionMeta - The TransactionMeta object to update.\n * @param signedTx - The encompassing type for all transaction types containing r, s, and v values.\n * @returns The updated TransactionMeta object.\n */\n private updateTransactionMetaRSV(\n transactionMeta: TransactionMeta,\n signedTx: TypedTransaction,\n ): TransactionMeta {\n const transactionMetaWithRsv = cloneDeep(transactionMeta);\n\n for (const key of ['r', 's', 'v'] as const) {\n const value = signedTx[key];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n transactionMetaWithRsv[key] = add0x(value.toString(16));\n }\n\n return transactionMetaWithRsv;\n }\n\n private async getEIP1559Compatibility(networkClientId?: NetworkClientId) {\n const currentNetworkIsEIP1559Compatible =\n await this.getCurrentNetworkEIP1559Compatibility(networkClientId);\n\n const currentAccountIsEIP1559Compatible =\n await this.getCurrentAccountEIP1559Compatibility();\n\n return (\n currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible\n );\n }\n\n private async signTransaction(\n transactionMeta: TransactionMeta,\n txParams: TransactionParams,\n ): Promise {\n log('Signing transaction', txParams);\n\n const unsignedEthTx = this.prepareUnsignedEthTx(\n transactionMeta.chainId,\n txParams,\n );\n\n this.approvingTransactionIds.add(transactionMeta.id);\n\n const signedTx = await new Promise((resolve, reject) => {\n this.sign?.(\n unsignedEthTx,\n txParams.from,\n ...this.getAdditionalSignArguments(transactionMeta),\n ).then(resolve, reject);\n\n this.signAbortCallbacks.set(transactionMeta.id, () =>\n reject(new Error('Signing aborted by user')),\n );\n });\n\n this.signAbortCallbacks.delete(transactionMeta.id);\n\n if (!signedTx) {\n log('Skipping signed status as no signed transaction');\n return undefined;\n }\n\n const transactionMetaFromHook = cloneDeep(transactionMeta);\n if (!this.afterSign(transactionMetaFromHook, signedTx)) {\n this.updateTransaction(\n transactionMetaFromHook,\n 'TransactionController#signTransaction - Update after sign',\n );\n\n log('Skipping signed status based on hook');\n\n return undefined;\n }\n\n const transactionMetaWithRsv = {\n ...this.updateTransactionMetaRSV(transactionMetaFromHook, signedTx),\n status: TransactionStatus.signed as const,\n };\n\n this.updateTransaction(\n transactionMetaWithRsv,\n 'TransactionController#approveTransaction - Transaction signed',\n );\n\n this.onTransactionStatusChange(transactionMetaWithRsv);\n\n const rawTx = bufferToHex(signedTx.serialize());\n\n const transactionMetaWithRawTx = merge({}, transactionMetaWithRsv, {\n rawTx,\n });\n\n this.updateTransaction(\n transactionMetaWithRawTx,\n 'TransactionController#approveTransaction - RawTransaction added',\n );\n\n return rawTx;\n }\n\n private onTransactionStatusChange(transactionMeta: TransactionMeta) {\n this.messagingSystem.publish(`${controllerName}:transactionStatusUpdated`, {\n transactionMeta,\n });\n }\n\n private getNonceTrackerTransactions(\n status: TransactionStatus,\n address: string,\n chainId: string = this.getChainId(),\n ) {\n return getAndFormatTransactionsForNonceTracker(\n chainId,\n address,\n status,\n this.state.transactions,\n );\n }\n\n private onConfirmedTransaction(transactionMeta: TransactionMeta) {\n log('Processing confirmed transaction', transactionMeta.id);\n\n this.markNonceDuplicatesDropped(transactionMeta.id);\n\n this.messagingSystem.publish(\n `${controllerName}:transactionConfirmed`,\n transactionMeta,\n );\n\n this.onTransactionStatusChange(transactionMeta);\n\n // Intentional given potential duration of process.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.updatePostBalance(transactionMeta);\n }\n\n private async updatePostBalance(transactionMeta: TransactionMeta) {\n try {\n if (transactionMeta.type !== TransactionType.swap) {\n return;\n }\n\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId: transactionMeta.networkClientId,\n chainId: transactionMeta.chainId,\n });\n const { updatedTransactionMeta, approvalTransactionMeta } =\n await updatePostTransactionBalance(transactionMeta, {\n ethQuery,\n getTransaction: this.getTransaction.bind(this),\n updateTransaction: this.updateTransaction.bind(this),\n });\n\n this.messagingSystem.publish(\n `${controllerName}:postTransactionBalanceUpdated`,\n {\n transactionMeta: updatedTransactionMeta,\n approvalTransactionMeta,\n },\n );\n } catch (error) {\n /* istanbul ignore next */\n log('Error while updating post transaction balance', error);\n }\n }\n\n #createNonceTracker({\n provider,\n blockTracker,\n chainId,\n }: {\n provider: Provider;\n blockTracker: BlockTracker;\n chainId?: Hex;\n }): NonceTracker {\n return new NonceTracker({\n // TODO: Fix types\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n provider: provider as any,\n // @ts-expect-error TODO: Fix types\n blockTracker,\n getPendingTransactions: this.#getNonceTrackerPendingTransactions.bind(\n this,\n chainId,\n ),\n getConfirmedTransactions: this.getNonceTrackerTransactions.bind(\n this,\n TransactionStatus.confirmed,\n ),\n });\n }\n\n #createIncomingTransactionHelper({\n blockTracker,\n etherscanRemoteTransactionSource,\n chainId,\n }: {\n blockTracker: BlockTracker;\n etherscanRemoteTransactionSource: EtherscanRemoteTransactionSource;\n chainId?: Hex;\n }): IncomingTransactionHelper {\n const incomingTransactionHelper = new IncomingTransactionHelper({\n blockTracker,\n getCurrentAccount: () => this.#getSelectedAccount(),\n getLastFetchedBlockNumbers: () => this.state.lastFetchedBlockNumbers,\n getChainId: chainId ? () => chainId : this.getChainId.bind(this),\n isEnabled: this.#incomingTransactionOptions.isEnabled,\n queryEntireHistory: this.#incomingTransactionOptions.queryEntireHistory,\n remoteTransactionSource: etherscanRemoteTransactionSource,\n transactionLimit: this.#transactionHistoryLimit,\n updateTransactions: this.#incomingTransactionOptions.updateTransactions,\n });\n\n this.#addIncomingTransactionHelperListeners(incomingTransactionHelper);\n\n return incomingTransactionHelper;\n }\n\n #createPendingTransactionTracker({\n provider,\n blockTracker,\n chainId,\n }: {\n provider: Provider;\n blockTracker: BlockTracker;\n chainId?: Hex;\n }): PendingTransactionTracker {\n const ethQuery = new EthQuery(provider);\n const getChainId = chainId ? () => chainId : this.getChainId.bind(this);\n\n const pendingTransactionTracker = new PendingTransactionTracker({\n blockTracker,\n getChainId,\n getEthQuery: () => ethQuery,\n getTransactions: () => this.state.transactions,\n isResubmitEnabled: this.#pendingTransactionOptions.isResubmitEnabled,\n getGlobalLock: () =>\n this.#multichainTrackingHelper.acquireNonceLockForChainIdKey({\n chainId: getChainId(),\n }),\n publishTransaction: this.publishTransaction.bind(this),\n hooks: {\n beforeCheckPendingTransaction:\n this.beforeCheckPendingTransaction.bind(this),\n beforePublish: this.beforePublish.bind(this),\n },\n });\n\n this.#addPendingTransactionTrackerListeners(pendingTransactionTracker);\n\n return pendingTransactionTracker;\n }\n\n #checkForPendingTransactionAndStartPolling = () => {\n // PendingTransactionTracker reads state through its getTransactions hook\n this.pendingTransactionTracker.startIfPendingTransactions();\n this.#multichainTrackingHelper.checkForPendingTransactionAndStartPolling();\n };\n\n #stopAllTracking() {\n this.pendingTransactionTracker.stop();\n this.#removePendingTransactionTrackerListeners(\n this.pendingTransactionTracker,\n );\n this.incomingTransactionHelper.stop();\n this.#removeIncomingTransactionHelperListeners(\n this.incomingTransactionHelper,\n );\n\n this.#multichainTrackingHelper.stopAllTracking();\n }\n\n #removeIncomingTransactionHelperListeners(\n incomingTransactionHelper: IncomingTransactionHelper,\n ) {\n incomingTransactionHelper.hub.removeAllListeners('transactions');\n incomingTransactionHelper.hub.removeAllListeners(\n 'updatedLastFetchedBlockNumbers',\n );\n }\n\n #addIncomingTransactionHelperListeners(\n incomingTransactionHelper: IncomingTransactionHelper,\n ) {\n incomingTransactionHelper.hub.on(\n 'transactions',\n this.onIncomingTransactions.bind(this),\n );\n incomingTransactionHelper.hub.on(\n 'updatedLastFetchedBlockNumbers',\n this.onUpdatedLastFetchedBlockNumbers.bind(this),\n );\n }\n\n #removePendingTransactionTrackerListeners(\n pendingTransactionTracker: PendingTransactionTracker,\n ) {\n pendingTransactionTracker.hub.removeAllListeners('transaction-confirmed');\n pendingTransactionTracker.hub.removeAllListeners('transaction-dropped');\n pendingTransactionTracker.hub.removeAllListeners('transaction-failed');\n pendingTransactionTracker.hub.removeAllListeners('transaction-updated');\n }\n\n #addPendingTransactionTrackerListeners(\n pendingTransactionTracker: PendingTransactionTracker,\n ) {\n pendingTransactionTracker.hub.on(\n 'transaction-confirmed',\n this.onConfirmedTransaction.bind(this),\n );\n\n pendingTransactionTracker.hub.on(\n 'transaction-dropped',\n this.setTransactionStatusDropped.bind(this),\n );\n\n pendingTransactionTracker.hub.on(\n 'transaction-failed',\n this.failTransaction.bind(this),\n );\n\n pendingTransactionTracker.hub.on(\n 'transaction-updated',\n this.updateTransaction.bind(this),\n );\n }\n\n #getNonceTrackerPendingTransactions(\n chainId: string | undefined,\n address: string,\n ) {\n const standardPendingTransactions = this.getNonceTrackerTransactions(\n TransactionStatus.submitted,\n address,\n chainId,\n );\n\n const externalPendingTransactions = this.getExternalPendingTransactions(\n address,\n chainId,\n );\n return [...standardPendingTransactions, ...externalPendingTransactions];\n }\n\n private async publishTransactionForRetry(\n ethQuery: EthQuery,\n rawTx: string,\n transactionMeta: TransactionMeta,\n ): Promise {\n try {\n const hash = await this.publishTransaction(ethQuery, rawTx);\n return hash;\n } catch (error: unknown) {\n if (this.isTransactionAlreadyConfirmedError(error as Error)) {\n await this.pendingTransactionTracker.forceCheckTransaction(\n transactionMeta,\n );\n throw new Error('Previous transaction is already confirmed');\n }\n throw error;\n }\n }\n\n /**\n * Ensures that error is a nonce issue\n *\n * @param error - The error to check\n * @returns Whether or not the error is a nonce issue\n */\n // TODO: Replace `any` with type\n // Some networks are returning original error in the data field\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private isTransactionAlreadyConfirmedError(error: any): boolean {\n return (\n error?.message?.includes('nonce too low') ||\n error?.data?.message?.includes('nonce too low')\n );\n }\n\n #getGasFeeFlows(): GasFeeFlow[] {\n if (this.#testGasFeeFlows) {\n return [new TestGasFeeFlow()];\n }\n\n return [new LineaGasFeeFlow(), new DefaultGasFeeFlow()];\n }\n\n #getLayer1GasFeeFlows(): Layer1GasFeeFlow[] {\n return [new OptimismLayer1GasFeeFlow(), new ScrollLayer1GasFeeFlow()];\n }\n\n #updateTransactionInternal(\n {\n transactionId,\n note,\n skipHistory,\n skipValidation,\n }: {\n transactionId: string;\n note?: string;\n skipHistory?: boolean;\n skipValidation?: boolean;\n },\n callback: (transactionMeta: TransactionMeta) => TransactionMeta | void,\n ): Readonly {\n let updatedTransactionParams: (keyof TransactionParams)[] = [];\n\n this.update((state) => {\n const index = state.transactions.findIndex(\n ({ id }) => id === transactionId,\n );\n\n let transactionMeta = state.transactions[index];\n\n // eslint-disable-next-line n/callback-return\n transactionMeta = callback(transactionMeta) ?? transactionMeta;\n\n if (skipValidation !== true) {\n transactionMeta.txParams = normalizeTransactionParams(\n transactionMeta.txParams,\n );\n\n validateTxParams(transactionMeta.txParams);\n }\n\n updatedTransactionParams =\n this.#checkIfTransactionParamsUpdated(transactionMeta);\n\n const shouldSkipHistory = this.isHistoryDisabled || skipHistory;\n\n if (!shouldSkipHistory) {\n transactionMeta = updateTransactionHistory(\n transactionMeta,\n note ?? 'Transaction updated',\n );\n }\n state.transactions[index] = transactionMeta;\n });\n\n const transactionMeta = this.getTransaction(\n transactionId,\n ) as TransactionMeta;\n\n if (updatedTransactionParams.length > 0) {\n this.#onTransactionParamsUpdated(\n transactionMeta,\n updatedTransactionParams,\n );\n }\n\n return transactionMeta;\n }\n\n #checkIfTransactionParamsUpdated(newTransactionMeta: TransactionMeta) {\n const { id: transactionId, txParams: newParams } = newTransactionMeta;\n\n const originalParams = this.getTransaction(transactionId)?.txParams;\n\n if (!originalParams || isEqual(originalParams, newParams)) {\n return [];\n }\n\n const params = Object.keys(newParams) as (keyof TransactionParams)[];\n\n const updatedProperties = params.filter(\n (param) => newParams[param] !== originalParams[param],\n );\n\n log(\n 'Transaction parameters have been updated',\n transactionId,\n updatedProperties,\n originalParams,\n newParams,\n );\n\n return updatedProperties;\n }\n\n #onTransactionParamsUpdated(\n transactionMeta: TransactionMeta,\n updatedParams: (keyof TransactionParams)[],\n ) {\n if (\n (['to', 'value', 'data'] as const).some((param) =>\n updatedParams.includes(param),\n )\n ) {\n log('Updating simulation data due to transaction parameter update');\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#updateSimulationData(transactionMeta);\n }\n }\n\n async #updateSimulationData(transactionMeta: TransactionMeta) {\n const { id: transactionId, chainId, txParams } = transactionMeta;\n const { from, to, value, data } = txParams;\n\n let simulationData: SimulationData = {\n error: {\n code: SimulationErrorCode.Disabled,\n message: 'Simulation disabled',\n },\n tokenBalanceChanges: [],\n };\n\n if (this.#isSimulationEnabled()) {\n this.#updateTransactionInternal(\n { transactionId, skipHistory: true },\n (txMeta) => {\n txMeta.simulationData = undefined;\n },\n );\n\n simulationData = await getSimulationData({\n chainId,\n from: from as Hex,\n to: to as Hex,\n value: value as Hex,\n data: data as Hex,\n });\n }\n\n const finalTransactionMeta = this.getTransaction(transactionId);\n\n /* istanbul ignore if */\n if (!finalTransactionMeta) {\n log(\n 'Cannot update simulation data as transaction not found',\n transactionId,\n simulationData,\n );\n\n return;\n }\n\n this.#updateTransactionInternal(\n {\n transactionId,\n note: 'TransactionController#updateSimulationData - Update simulation data',\n },\n (txMeta) => {\n txMeta.simulationData = simulationData;\n },\n );\n\n log('Updated simulation data', transactionId, simulationData);\n }\n\n #onGasFeePollerTransactionUpdate({\n transactionId,\n gasFeeEstimates,\n gasFeeEstimatesLoaded,\n layer1GasFee,\n }: {\n transactionId: string;\n gasFeeEstimates?: GasFeeEstimates;\n gasFeeEstimatesLoaded?: boolean;\n layer1GasFee?: Hex;\n }) {\n this.#updateTransactionInternal(\n { transactionId, skipHistory: true },\n (txMeta) => {\n if (gasFeeEstimates) {\n txMeta.gasFeeEstimates = gasFeeEstimates;\n }\n\n if (gasFeeEstimatesLoaded !== undefined) {\n txMeta.gasFeeEstimatesLoaded = gasFeeEstimatesLoaded;\n }\n\n if (layer1GasFee) {\n txMeta.layer1GasFee = layer1GasFee;\n }\n },\n );\n }\n\n #getNetworkClientId({\n networkClientId: requestNetworkClientId,\n chainId,\n }: {\n networkClientId?: NetworkClientId;\n chainId?: Hex;\n }) {\n const globalChainId = this.#getGlobalChainId();\n const globalNetworkClientId = this.#getGlobalNetworkClientId();\n\n if (requestNetworkClientId) {\n return requestNetworkClientId;\n }\n\n if (!chainId || chainId === globalChainId) {\n return globalNetworkClientId;\n }\n\n return this.messagingSystem.call(\n `NetworkController:findNetworkClientIdByChainId`,\n chainId,\n );\n }\n\n #getGlobalNetworkClientId() {\n return this.getNetworkState().selectedNetworkClientId;\n }\n\n #getGlobalChainId() {\n return this.messagingSystem.call(\n `NetworkController:getNetworkClientById`,\n this.getNetworkState().selectedNetworkClientId,\n ).configuration.chainId;\n }\n\n #isCustomNetwork(networkClientId?: NetworkClientId) {\n const globalNetworkClientId = this.#getGlobalNetworkClientId();\n\n if (!networkClientId || networkClientId === globalNetworkClientId) {\n return !isInfuraNetworkType(\n this.getNetworkState().selectedNetworkClientId,\n );\n }\n\n return (\n this.messagingSystem.call(\n `NetworkController:getNetworkClientById`,\n networkClientId,\n ).configuration.type === NetworkClientType.Custom\n );\n }\n\n #getSelectedAccount() {\n return this.messagingSystem.call('AccountsController:getSelectedAccount');\n }\n}\n"]}
+\ No newline at end of file
+diff --git a/dist/chunk-YQYO6EGF.mjs b/dist/chunk-YQYO6EGF.mjs
+new file mode 100644
+index 0000000000000000000000000000000000000000..a055cb8a748cd205a7dab47019d1e1a747c20c05
+--- /dev/null
++++ b/dist/chunk-YQYO6EGF.mjs
+@@ -0,0 +1,2556 @@
++import {
++ getAndFormatTransactionsForNonceTracker,
++ getNextNonce
++} from "./chunk-6DDVVUJC.mjs";
++import {
++ getSimulationData
++} from "./chunk-EVL6KODQ.mjs";
++import {
++ determineTransactionType
++} from "./chunk-KG4UW4K4.mjs";
++import {
++ validateTransactionOrigin,
++ validateTxParams
++} from "./chunk-5ZEJT5SN.mjs";
++import {
++ PendingTransactionTracker
++} from "./chunk-7M2R5AHC.mjs";
++import {
++ validateConfirmedExternalTransaction
++} from "./chunk-FRKQ3Z2L.mjs";
++import {
++ addGasBuffer,
++ estimateGas,
++ updateGas
++} from "./chunk-5G6OHAXI.mjs";
++import {
++ addInitialHistorySnapshot,
++ updateTransactionHistory
++} from "./chunk-XGRAHX6T.mjs";
++import {
++ OptimismLayer1GasFeeFlow
++} from "./chunk-VEVVBHP3.mjs";
++import {
++ ScrollLayer1GasFeeFlow
++} from "./chunk-Z4GV3YQQ.mjs";
++import {
++ TestGasFeeFlow
++} from "./chunk-FMRLPVFZ.mjs";
++import {
++ GasFeePoller
++} from "./chunk-SFFTNB2X.mjs";
++import {
++ getTransactionLayer1GasFee,
++ updateTransactionLayer1GasFee
++} from "./chunk-NOHEXQ7Y.mjs";
++import {
++ IncomingTransactionHelper
++} from "./chunk-3ZV5YEUV.mjs";
++import {
++ MultichainTrackingHelper
++} from "./chunk-4V4XIPCI.mjs";
++import {
++ EtherscanRemoteTransactionSource
++} from "./chunk-EKJXGERC.mjs";
++import {
++ LineaGasFeeFlow
++} from "./chunk-UHG2LLVV.mjs";
++import {
++ DefaultGasFeeFlow
++} from "./chunk-H2KZOK3J.mjs";
++import {
++ updateGasFees
++} from "./chunk-VXNPVIYL.mjs";
++import {
++ updatePostTransactionBalance,
++ updateSwapsTransaction
++} from "./chunk-GNAL5HC2.mjs";
++import {
++ getIncreasedPriceFromExisting,
++ isEIP1559Transaction,
++ isFeeMarketEIP1559Values,
++ isGasPriceValue,
++ normalizeGasFeeValues,
++ normalizeTransactionParams,
++ normalizeTxError,
++ validateGasValues,
++ validateIfTransactionUnapproved,
++ validateMinimumIncrease
++} from "./chunk-Q56I5ONX.mjs";
++import {
++ getGasFeeFlow
++} from "./chunk-JXXTNVU4.mjs";
++import {
++ projectLogger
++} from "./chunk-UQQWZT6C.mjs";
++import {
++ __privateAdd,
++ __privateGet,
++ __privateMethod,
++ __privateSet
++} from "./chunk-XUI43LEZ.mjs";
++
++// src/TransactionController.ts
++import { Hardfork, Common } from "@ethereumjs/common";
++import { TransactionFactory } from "@ethereumjs/tx";
++import { bufferToHex } from "@ethereumjs/util";
++import { BaseController } from "@metamask/base-controller";
++import {
++ query,
++ ApprovalType,
++ ORIGIN_METAMASK,
++ convertHexToDecimal,
++ isInfuraNetworkType
++} from "@metamask/controller-utils";
++import EthQuery from "@metamask/eth-query";
++import { NetworkClientType } from "@metamask/network-controller";
++import { NonceTracker } from "@metamask/nonce-tracker";
++import { errorCodes, rpcErrors, providerErrors } from "@metamask/rpc-errors";
++import { add0x } from "@metamask/utils";
++import { Mutex } from "async-mutex";
++import { MethodRegistry } from "eth-method-registry";
++import { EventEmitter } from "events";
++import { cloneDeep, mapValues, merge, pickBy, sortBy, isEqual } from "lodash";
++import { v1 as random } from "uuid";
++var metadata = {
++ transactions: {
++ persist: true,
++ anonymous: false
++ },
++ methodData: {
++ persist: true,
++ anonymous: false
++ },
++ lastFetchedBlockNumbers: {
++ persist: true,
++ anonymous: false
++ }
++};
++var HARDFORK = Hardfork.London;
++var CANCEL_RATE = 1.1;
++var SPEED_UP_RATE = 1.1;
++var controllerName = "TransactionController";
++var ApprovalState = /* @__PURE__ */ ((ApprovalState2) => {
++ ApprovalState2["Approved"] = "approved";
++ ApprovalState2["NotApproved"] = "not-approved";
++ ApprovalState2["SkippedViaBeforePublishHook"] = "skipped-via-before-publish-hook";
++ return ApprovalState2;
++})(ApprovalState || {});
++function getDefaultTransactionControllerState() {
++ return {
++ methodData: {},
++ transactions: [],
++ lastFetchedBlockNumbers: {}
++ };
++}
++var _internalEvents, _incomingTransactionOptions, _pendingTransactionOptions, _transactionHistoryLimit, _isSimulationEnabled, _testGasFeeFlows, _multichainTrackingHelper, _createNonceTracker, createNonceTracker_fn, _createIncomingTransactionHelper, createIncomingTransactionHelper_fn, _createPendingTransactionTracker, createPendingTransactionTracker_fn, _checkForPendingTransactionAndStartPolling, _stopAllTracking, stopAllTracking_fn, _removeIncomingTransactionHelperListeners, removeIncomingTransactionHelperListeners_fn, _addIncomingTransactionHelperListeners, addIncomingTransactionHelperListeners_fn, _removePendingTransactionTrackerListeners, removePendingTransactionTrackerListeners_fn, _addPendingTransactionTrackerListeners, addPendingTransactionTrackerListeners_fn, _getNonceTrackerPendingTransactions, getNonceTrackerPendingTransactions_fn, _getGasFeeFlows, getGasFeeFlows_fn, _getLayer1GasFeeFlows, getLayer1GasFeeFlows_fn, _updateTransactionInternal, updateTransactionInternal_fn, _checkIfTransactionParamsUpdated, checkIfTransactionParamsUpdated_fn, _onTransactionParamsUpdated, onTransactionParamsUpdated_fn, _updateSimulationData, updateSimulationData_fn, _onGasFeePollerTransactionUpdate, onGasFeePollerTransactionUpdate_fn, _getNetworkClientId, getNetworkClientId_fn, _getGlobalNetworkClientId, getGlobalNetworkClientId_fn, _getGlobalChainId, getGlobalChainId_fn, _isCustomNetwork, isCustomNetwork_fn, _getSelectedAccount, getSelectedAccount_fn;
++var TransactionController = class extends BaseController {
++ /**
++ * Constructs a TransactionController.
++ *
++ * @param options - The controller options.
++ * @param options.blockTracker - The block tracker used to poll for new blocks data.
++ * @param options.disableHistory - Whether to disable storing history in transaction metadata.
++ * @param options.disableSendFlowHistory - Explicitly disable transaction metadata history.
++ * @param options.disableSwaps - Whether to disable additional processing on swaps transactions.
++ * @param options.getCurrentAccountEIP1559Compatibility - Whether or not the account supports EIP-1559.
++ * @param options.getCurrentNetworkEIP1559Compatibility - Whether or not the network supports EIP-1559.
++ * @param options.getExternalPendingTransactions - Callback to retrieve pending transactions from external sources.
++ * @param options.getGasFeeEstimates - Callback to retrieve gas fee estimates.
++ * @param options.getNetworkClientRegistry - Gets the network client registry.
++ * @param options.getNetworkState - Gets the state of the network controller.
++ * @param options.getPermittedAccounts - Get accounts that a given origin has permissions for.
++ * @param options.getSavedGasFees - Gets the saved gas fee config.
++ * @param options.incomingTransactions - Configuration options for incoming transaction support.
++ * @param options.isMultichainEnabled - Enable multichain support.
++ * @param options.isSimulationEnabled - Whether new transactions will be automatically simulated.
++ * @param options.messenger - The controller messenger.
++ * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.
++ * @param options.pendingTransactions - Configuration options for pending transaction support.
++ * @param options.provider - The provider used to create the underlying EthQuery instance.
++ * @param options.securityProviderRequest - A function for verifying a transaction, whether it is malicious or not.
++ * @param options.sign - Function used to sign transactions.
++ * @param options.state - Initial state to set on this controller.
++ * @param options.testGasFeeFlows - Whether to use the test gas fee flow.
++ * @param options.transactionHistoryLimit - Transaction history limit.
++ * @param options.hooks - The controller hooks.
++ */
++ constructor({
++ blockTracker,
++ disableHistory,
++ disableSendFlowHistory,
++ disableSwaps,
++ getCurrentAccountEIP1559Compatibility,
++ getCurrentNetworkEIP1559Compatibility,
++ getExternalPendingTransactions,
++ getGasFeeEstimates,
++ getNetworkClientRegistry,
++ getNetworkState,
++ getPermittedAccounts,
++ getSavedGasFees,
++ incomingTransactions = {},
++ isMultichainEnabled = false,
++ isSimulationEnabled,
++ messenger,
++ onNetworkStateChange,
++ pendingTransactions = {},
++ provider,
++ securityProviderRequest,
++ sign,
++ state,
++ testGasFeeFlows,
++ transactionHistoryLimit = 40,
++ hooks
++ }) {
++ super({
++ name: controllerName,
++ metadata,
++ messenger,
++ state: {
++ ...getDefaultTransactionControllerState(),
++ ...state
++ }
++ });
++ __privateAdd(this, _createNonceTracker);
++ __privateAdd(this, _createIncomingTransactionHelper);
++ __privateAdd(this, _createPendingTransactionTracker);
++ __privateAdd(this, _stopAllTracking);
++ __privateAdd(this, _removeIncomingTransactionHelperListeners);
++ __privateAdd(this, _addIncomingTransactionHelperListeners);
++ __privateAdd(this, _removePendingTransactionTrackerListeners);
++ __privateAdd(this, _addPendingTransactionTrackerListeners);
++ __privateAdd(this, _getNonceTrackerPendingTransactions);
++ __privateAdd(this, _getGasFeeFlows);
++ __privateAdd(this, _getLayer1GasFeeFlows);
++ __privateAdd(this, _updateTransactionInternal);
++ __privateAdd(this, _checkIfTransactionParamsUpdated);
++ __privateAdd(this, _onTransactionParamsUpdated);
++ __privateAdd(this, _updateSimulationData);
++ __privateAdd(this, _onGasFeePollerTransactionUpdate);
++ __privateAdd(this, _getNetworkClientId);
++ __privateAdd(this, _getGlobalNetworkClientId);
++ __privateAdd(this, _getGlobalChainId);
++ __privateAdd(this, _isCustomNetwork);
++ __privateAdd(this, _getSelectedAccount);
++ __privateAdd(this, _internalEvents, new EventEmitter());
++ this.approvingTransactionIds = /* @__PURE__ */ new Set();
++ this.mutex = new Mutex();
++ __privateAdd(this, _incomingTransactionOptions, void 0);
++ __privateAdd(this, _pendingTransactionOptions, void 0);
++ this.signAbortCallbacks = /* @__PURE__ */ new Map();
++ __privateAdd(this, _transactionHistoryLimit, void 0);
++ __privateAdd(this, _isSimulationEnabled, void 0);
++ __privateAdd(this, _testGasFeeFlows, void 0);
++ __privateAdd(this, _multichainTrackingHelper, void 0);
++ __privateAdd(this, _checkForPendingTransactionAndStartPolling, () => {
++ this.pendingTransactionTracker.startIfPendingTransactions();
++ __privateGet(this, _multichainTrackingHelper).checkForPendingTransactionAndStartPolling();
++ });
++ this.messagingSystem = messenger;
++ this.getNetworkState = getNetworkState;
++ this.isSendFlowHistoryDisabled = disableSendFlowHistory ?? false;
++ this.isHistoryDisabled = disableHistory ?? false;
++ this.isSwapsDisabled = disableSwaps ?? false;
++ __privateSet(this, _isSimulationEnabled, isSimulationEnabled ?? (() => true));
++ this.registry = new MethodRegistry({ provider });
++ this.getSavedGasFees = getSavedGasFees ?? ((_chainId) => void 0);
++ this.getCurrentAccountEIP1559Compatibility = getCurrentAccountEIP1559Compatibility ?? (() => Promise.resolve(true));
++ this.getCurrentNetworkEIP1559Compatibility = getCurrentNetworkEIP1559Compatibility;
++ this.getGasFeeEstimates = getGasFeeEstimates || (() => Promise.resolve({}));
++ this.getPermittedAccounts = getPermittedAccounts;
++ this.getExternalPendingTransactions = getExternalPendingTransactions ?? (() => []);
++ this.securityProviderRequest = securityProviderRequest;
++ __privateSet(this, _incomingTransactionOptions, incomingTransactions);
++ __privateSet(this, _pendingTransactionOptions, pendingTransactions);
++ __privateSet(this, _transactionHistoryLimit, transactionHistoryLimit);
++ this.sign = sign;
++ __privateSet(this, _testGasFeeFlows, testGasFeeFlows === true);
++ this.afterSign = hooks?.afterSign ?? (() => true);
++ this.beforeCheckPendingTransaction = hooks?.beforeCheckPendingTransaction ?? /* istanbul ignore next */
++ (() => true);
++ this.beforePublish = hooks?.beforePublish ?? (() => true);
++ this.getAdditionalSignArguments = hooks?.getAdditionalSignArguments ?? (() => []);
++ this.publish = hooks?.publish ?? (() => Promise.resolve({ transactionHash: void 0 }));
++ this.nonceTracker = __privateMethod(this, _createNonceTracker, createNonceTracker_fn).call(this, {
++ provider,
++ blockTracker
++ });
++ const findNetworkClientIdByChainId = (chainId) => {
++ return this.messagingSystem.call(
++ `NetworkController:findNetworkClientIdByChainId`,
++ chainId
++ );
++ };
++ __privateSet(this, _multichainTrackingHelper, new MultichainTrackingHelper({
++ isMultichainEnabled,
++ provider,
++ nonceTracker: this.nonceTracker,
++ incomingTransactionOptions: incomingTransactions,
++ findNetworkClientIdByChainId,
++ getNetworkClientById: (networkClientId) => {
++ return this.messagingSystem.call(
++ `NetworkController:getNetworkClientById`,
++ networkClientId
++ );
++ },
++ getNetworkClientRegistry,
++ removeIncomingTransactionHelperListeners: __privateMethod(this, _removeIncomingTransactionHelperListeners, removeIncomingTransactionHelperListeners_fn).bind(this),
++ removePendingTransactionTrackerListeners: __privateMethod(this, _removePendingTransactionTrackerListeners, removePendingTransactionTrackerListeners_fn).bind(this),
++ createNonceTracker: __privateMethod(this, _createNonceTracker, createNonceTracker_fn).bind(this),
++ createIncomingTransactionHelper: __privateMethod(this, _createIncomingTransactionHelper, createIncomingTransactionHelper_fn).bind(this),
++ createPendingTransactionTracker: __privateMethod(this, _createPendingTransactionTracker, createPendingTransactionTracker_fn).bind(this),
++ onNetworkStateChange: (listener) => {
++ this.messagingSystem.subscribe(
++ "NetworkController:stateChange",
++ listener
++ );
++ }
++ }));
++ __privateGet(this, _multichainTrackingHelper).initialize();
++ const etherscanRemoteTransactionSource = new EtherscanRemoteTransactionSource({
++ includeTokenTransfers: incomingTransactions.includeTokenTransfers
++ });
++ this.incomingTransactionHelper = __privateMethod(this, _createIncomingTransactionHelper, createIncomingTransactionHelper_fn).call(this, {
++ blockTracker,
++ etherscanRemoteTransactionSource
++ });
++ this.pendingTransactionTracker = __privateMethod(this, _createPendingTransactionTracker, createPendingTransactionTracker_fn).call(this, {
++ provider,
++ blockTracker
++ });
++ this.gasFeeFlows = __privateMethod(this, _getGasFeeFlows, getGasFeeFlows_fn).call(this);
++ this.layer1GasFeeFlows = __privateMethod(this, _getLayer1GasFeeFlows, getLayer1GasFeeFlows_fn).call(this);
++ const gasFeePoller = new GasFeePoller({
++ findNetworkClientIdByChainId,
++ gasFeeFlows: this.gasFeeFlows,
++ getGasFeeControllerEstimates: this.getGasFeeEstimates,
++ getProvider: (chainId, networkClientId) => __privateGet(this, _multichainTrackingHelper).getProvider({
++ networkClientId,
++ chainId
++ }),
++ getTransactions: () => this.state.transactions,
++ layer1GasFeeFlows: this.layer1GasFeeFlows,
++ onStateChange: (listener) => {
++ this.messagingSystem.subscribe(
++ "TransactionController:stateChange",
++ listener
++ );
++ }
++ });
++ gasFeePoller.hub.on(
++ "transaction-updated",
++ __privateMethod(this, _onGasFeePollerTransactionUpdate, onGasFeePollerTransactionUpdate_fn).bind(this)
++ );
++ this.messagingSystem.subscribe(
++ "TransactionController:stateChange",
++ __privateGet(this, _checkForPendingTransactionAndStartPolling)
++ );
++ onNetworkStateChange(() => {
++ projectLogger("Detected network change", this.getChainId());
++ this.pendingTransactionTracker.startIfPendingTransactions();
++ this.onBootCleanup();
++ });
++ this.onBootCleanup();
++ __privateGet(this, _checkForPendingTransactionAndStartPolling).call(this);
++ }
++ failTransaction(transactionMeta, error, actionId) {
++ let newTransactionMeta;
++ try {
++ newTransactionMeta = __privateMethod(this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, {
++ transactionId: transactionMeta.id,
++ note: "TransactionController#failTransaction - Add error message and set status to failed",
++ skipValidation: true
++ }, (draftTransactionMeta) => {
++ draftTransactionMeta.status = "failed" /* failed */;
++ draftTransactionMeta.error = normalizeTxError(error);
++ });
++ } catch (err) {
++ projectLogger("Failed to mark transaction as failed", err);
++ newTransactionMeta = {
++ ...transactionMeta,
++ status: "failed" /* failed */,
++ error: normalizeTxError(error)
++ };
++ }
++ this.messagingSystem.publish(`${controllerName}:transactionFailed`, {
++ actionId,
++ error: error.message,
++ transactionMeta: newTransactionMeta
++ });
++ this.onTransactionStatusChange(newTransactionMeta);
++ this.messagingSystem.publish(
++ `${controllerName}:transactionFinished`,
++ newTransactionMeta
++ );
++ __privateGet(this, _internalEvents).emit(
++ `${transactionMeta.id}:finished`,
++ newTransactionMeta
++ );
++ }
++ async registryLookup(fourBytePrefix) {
++ const registryMethod = await this.registry.lookup(fourBytePrefix);
++ if (!registryMethod) {
++ return {
++ registryMethod: "",
++ parsedRegistryMethod: { name: void 0, args: void 0 }
++ };
++ }
++ const parsedRegistryMethod = this.registry.parse(registryMethod);
++ return { registryMethod, parsedRegistryMethod };
++ }
++ /**
++ * Stops polling and removes listeners to prepare the controller for garbage collection.
++ */
++ destroy() {
++ __privateMethod(this, _stopAllTracking, stopAllTracking_fn).call(this);
++ }
++ /**
++ * Handle new method data request.
++ *
++ * @param fourBytePrefix - The method prefix.
++ * @returns The method data object corresponding to the given signature prefix.
++ */
++ async handleMethodData(fourBytePrefix) {
++ const releaseLock = await this.mutex.acquire();
++ try {
++ const { methodData } = this.state;
++ const knownMethod = Object.keys(methodData).find(
++ (knownFourBytePrefix) => fourBytePrefix === knownFourBytePrefix
++ );
++ if (knownMethod) {
++ return methodData[fourBytePrefix];
++ }
++ const registry = await this.registryLookup(fourBytePrefix);
++ this.update((state) => {
++ state.methodData[fourBytePrefix] = registry;
++ });
++ return registry;
++ } finally {
++ releaseLock();
++ }
++ }
++ /**
++ * Add a new unapproved transaction to state. Parameters will be validated, a
++ * unique transaction id will be generated, and gas and gasPrice will be calculated
++ * if not provided. If A `:unapproved` hub event will be emitted once added.
++ *
++ * @param txParams - Standard parameters for an Ethereum transaction.
++ * @param opts - Additional options to control how the transaction is added.
++ * @param opts.actionId - Unique ID to prevent duplicate requests.
++ * @param opts.deviceConfirmedOn - An enum to indicate what device confirmed the transaction.
++ * @param opts.method - RPC method that requested the transaction.
++ * @param opts.origin - The origin of the transaction request, such as a dApp hostname.
++ * @param opts.requireApproval - Whether the transaction requires approval by the user, defaults to true unless explicitly disabled.
++ * @param opts.securityAlertResponse - Response from security validator.
++ * @param opts.sendFlowHistory - The sendFlowHistory entries to add.
++ * @param opts.type - Type of transaction to add, such as 'cancel' or 'swap'.
++ * @param opts.swaps - Options for swaps transactions.
++ * @param opts.swaps.hasApproveTx - Whether the transaction has an approval transaction.
++ * @param opts.swaps.meta - Metadata for swap transaction.
++ * @param opts.networkClientId - The id of the network client for this transaction.
++ * @returns Object containing a promise resolving to the transaction hash if approved.
++ */
++ async addTransaction(txParams, {
++ actionId,
++ deviceConfirmedOn,
++ method,
++ origin,
++ requireApproval,
++ securityAlertResponse,
++ sendFlowHistory,
++ swaps = {},
++ type,
++ networkClientId: requestNetworkClientId
++ } = {}) {
++ projectLogger("Adding transaction", txParams);
++ txParams = normalizeTransactionParams(txParams);
++ if (requestNetworkClientId && !__privateGet(this, _multichainTrackingHelper).has(requestNetworkClientId)) {
++ throw new Error(
++ "The networkClientId for this transaction could not be found"
++ );
++ }
++ const networkClientId = requestNetworkClientId ?? __privateMethod(this, _getGlobalNetworkClientId, getGlobalNetworkClientId_fn).call(this);
++ const isEIP1559Compatible = await this.getEIP1559Compatibility(
++ networkClientId
++ );
++ validateTxParams(txParams, isEIP1559Compatible);
++ if (origin) {
++ await validateTransactionOrigin(
++ await this.getPermittedAccounts(origin),
++ __privateMethod(this, _getSelectedAccount, getSelectedAccount_fn).call(this).address,
++ txParams.from,
++ origin
++ );
++ }
++ const dappSuggestedGasFees = this.generateDappSuggestedGasFees(
++ txParams,
++ origin
++ );
++ const chainId = this.getChainId(networkClientId);
++ const ethQuery = __privateGet(this, _multichainTrackingHelper).getEthQuery({
++ networkClientId,
++ chainId
++ });
++ const transactionType = type ?? (await determineTransactionType(txParams, ethQuery)).type;
++ const existingTransactionMeta = this.getTransactionWithActionId(actionId);
++ let addedTransactionMeta = existingTransactionMeta ? cloneDeep(existingTransactionMeta) : {
++ // Add actionId to txMeta to check if same actionId is seen again
++ actionId,
++ chainId,
++ dappSuggestedGasFees,
++ deviceConfirmedOn,
++ id: random(),
++ origin,
++ securityAlertResponse,
++ status: "unapproved" /* unapproved */,
++ time: Date.now(),
++ txParams,
++ userEditedGasLimit: false,
++ verifiedOnBlockchain: false,
++ type: transactionType,
++ networkClientId
++ };
++ await this.updateGasProperties(addedTransactionMeta);
++ if (!existingTransactionMeta) {
++ if (method && this.securityProviderRequest) {
++ const securityProviderResponse = await this.securityProviderRequest(
++ addedTransactionMeta,
++ method
++ );
++ addedTransactionMeta.securityProviderResponse = securityProviderResponse;
++ }
++ if (!this.isSendFlowHistoryDisabled) {
++ addedTransactionMeta.sendFlowHistory = sendFlowHistory ?? [];
++ }
++ if (!this.isHistoryDisabled) {
++ addedTransactionMeta = addInitialHistorySnapshot(addedTransactionMeta);
++ }
++ addedTransactionMeta = updateSwapsTransaction(
++ addedTransactionMeta,
++ transactionType,
++ swaps,
++ {
++ isSwapsDisabled: this.isSwapsDisabled,
++ cancelTransaction: this.cancelTransaction.bind(this),
++ messenger: this.messagingSystem
++ }
++ );
++ this.addMetadata(addedTransactionMeta);
++ if (requireApproval !== false) {
++ __privateMethod(this, _updateSimulationData, updateSimulationData_fn).call(this, addedTransactionMeta);
++ } else {
++ projectLogger("Skipping simulation as approval not required");
++ }
++ this.messagingSystem.publish(
++ `${controllerName}:unapprovedTransactionAdded`,
++ addedTransactionMeta
++ );
++ }
++ return {
++ result: this.processApproval(addedTransactionMeta, {
++ isExisting: Boolean(existingTransactionMeta),
++ requireApproval,
++ actionId
++ }),
++ transactionMeta: addedTransactionMeta
++ };
++ }
++ startIncomingTransactionPolling(networkClientIds = []) {
++ if (networkClientIds.length === 0) {
++ this.incomingTransactionHelper.start();
++ return;
++ }
++ __privateGet(this, _multichainTrackingHelper).startIncomingTransactionPolling(
++ networkClientIds
++ );
++ }
++ stopIncomingTransactionPolling(networkClientIds = []) {
++ if (networkClientIds.length === 0) {
++ this.incomingTransactionHelper.stop();
++ return;
++ }
++ __privateGet(this, _multichainTrackingHelper).stopIncomingTransactionPolling(
++ networkClientIds
++ );
++ }
++ stopAllIncomingTransactionPolling() {
++ this.incomingTransactionHelper.stop();
++ __privateGet(this, _multichainTrackingHelper).stopAllIncomingTransactionPolling();
++ }
++ async updateIncomingTransactions(networkClientIds = []) {
++ if (networkClientIds.length === 0) {
++ await this.incomingTransactionHelper.update();
++ return;
++ }
++ await __privateGet(this, _multichainTrackingHelper).updateIncomingTransactions(
++ networkClientIds
++ );
++ }
++ /**
++ * Attempts to cancel a transaction based on its ID by setting its status to "rejected"
++ * and emitting a `:finished` hub event.
++ *
++ * @param transactionId - The ID of the transaction to cancel.
++ * @param gasValues - The gas values to use for the cancellation transaction.
++ * @param options - The options for the cancellation transaction.
++ * @param options.actionId - Unique ID to prevent duplicate requests.
++ * @param options.estimatedBaseFee - The estimated base fee of the transaction.
++ */
++ async stopTransaction(transactionId, gasValues, {
++ estimatedBaseFee,
++ actionId
++ } = {}) {
++ if (this.getTransactionWithActionId(actionId)) {
++ return;
++ }
++ if (gasValues) {
++ gasValues = normalizeGasFeeValues(gasValues);
++ validateGasValues(gasValues);
++ }
++ projectLogger("Creating cancel transaction", transactionId, gasValues);
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ return;
++ }
++ if (!this.sign) {
++ throw new Error("No sign method defined.");
++ }
++ const minGasPrice = getIncreasedPriceFromExisting(
++ transactionMeta.txParams.gasPrice,
++ CANCEL_RATE
++ );
++ const gasPriceFromValues = isGasPriceValue(gasValues) && gasValues.gasPrice;
++ const newGasPrice = gasPriceFromValues && validateMinimumIncrease(gasPriceFromValues, minGasPrice) || minGasPrice;
++ const existingMaxFeePerGas = transactionMeta.txParams?.maxFeePerGas;
++ const minMaxFeePerGas = getIncreasedPriceFromExisting(
++ existingMaxFeePerGas,
++ CANCEL_RATE
++ );
++ const maxFeePerGasValues = isFeeMarketEIP1559Values(gasValues) && gasValues.maxFeePerGas;
++ const newMaxFeePerGas = maxFeePerGasValues && validateMinimumIncrease(maxFeePerGasValues, minMaxFeePerGas) || existingMaxFeePerGas && minMaxFeePerGas;
++ const existingMaxPriorityFeePerGas = transactionMeta.txParams?.maxPriorityFeePerGas;
++ const minMaxPriorityFeePerGas = getIncreasedPriceFromExisting(
++ existingMaxPriorityFeePerGas,
++ CANCEL_RATE
++ );
++ const maxPriorityFeePerGasValues = isFeeMarketEIP1559Values(gasValues) && gasValues.maxPriorityFeePerGas;
++ const newMaxPriorityFeePerGas = maxPriorityFeePerGasValues && validateMinimumIncrease(
++ maxPriorityFeePerGasValues,
++ minMaxPriorityFeePerGas
++ ) || existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas;
++ const newTxParams = newMaxFeePerGas && newMaxPriorityFeePerGas ? {
++ from: transactionMeta.txParams.from,
++ gasLimit: transactionMeta.txParams.gas,
++ maxFeePerGas: newMaxFeePerGas,
++ maxPriorityFeePerGas: newMaxPriorityFeePerGas,
++ type: "0x2" /* feeMarket */,
++ nonce: transactionMeta.txParams.nonce,
++ to: transactionMeta.txParams.from,
++ value: "0x0"
++ } : {
++ from: transactionMeta.txParams.from,
++ gasLimit: transactionMeta.txParams.gas,
++ gasPrice: newGasPrice,
++ nonce: transactionMeta.txParams.nonce,
++ to: transactionMeta.txParams.from,
++ value: "0x0"
++ };
++ const unsignedEthTx = this.prepareUnsignedEthTx(
++ transactionMeta.chainId,
++ newTxParams
++ );
++ const signedTx = await this.sign(
++ unsignedEthTx,
++ transactionMeta.txParams.from
++ );
++ const rawTx = bufferToHex(signedTx.serialize());
++ const newFee = newTxParams.maxFeePerGas ?? newTxParams.gasPrice;
++ const oldFee = newTxParams.maxFeePerGas ? transactionMeta.txParams.maxFeePerGas : transactionMeta.txParams.gasPrice;
++ projectLogger("Submitting cancel transaction", {
++ oldFee,
++ newFee,
++ txParams: newTxParams
++ });
++ const ethQuery = __privateGet(this, _multichainTrackingHelper).getEthQuery({
++ networkClientId: transactionMeta.networkClientId,
++ chainId: transactionMeta.chainId
++ });
++ const hash = await this.publishTransactionForRetry(
++ ethQuery,
++ rawTx,
++ transactionMeta
++ );
++ const cancelTransactionMeta = {
++ actionId,
++ chainId: transactionMeta.chainId,
++ networkClientId: transactionMeta.networkClientId,
++ estimatedBaseFee,
++ hash,
++ id: random(),
++ originalGasEstimate: transactionMeta.txParams.gas,
++ rawTx,
++ status: "submitted" /* submitted */,
++ time: Date.now(),
++ type: "cancel" /* cancel */,
++ txParams: newTxParams
++ };
++ this.addMetadata(cancelTransactionMeta);
++ this.messagingSystem.publish(`${controllerName}:transactionApproved`, {
++ transactionMeta: cancelTransactionMeta,
++ actionId
++ });
++ this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {
++ transactionMeta: cancelTransactionMeta,
++ actionId
++ });
++ this.messagingSystem.publish(
++ `${controllerName}:transactionFinished`,
++ cancelTransactionMeta
++ );
++ __privateGet(this, _internalEvents).emit(
++ `${transactionMeta.id}:finished`,
++ cancelTransactionMeta
++ );
++ }
++ /**
++ * Attempts to speed up a transaction increasing transaction gasPrice by ten percent.
++ *
++ * @param transactionId - The ID of the transaction to speed up.
++ * @param gasValues - The gas values to use for the speed up transaction.
++ * @param options - The options for the speed up transaction.
++ * @param options.actionId - Unique ID to prevent duplicate requests
++ * @param options.estimatedBaseFee - The estimated base fee of the transaction.
++ */
++ async speedUpTransaction(transactionId, gasValues, {
++ actionId,
++ estimatedBaseFee
++ } = {}) {
++ if (this.getTransactionWithActionId(actionId)) {
++ return;
++ }
++ if (gasValues) {
++ gasValues = normalizeGasFeeValues(gasValues);
++ validateGasValues(gasValues);
++ }
++ projectLogger("Creating speed up transaction", transactionId, gasValues);
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ return;
++ }
++ if (!this.sign) {
++ throw new Error("No sign method defined.");
++ }
++ const minGasPrice = getIncreasedPriceFromExisting(
++ transactionMeta.txParams.gasPrice,
++ SPEED_UP_RATE
++ );
++ const gasPriceFromValues = isGasPriceValue(gasValues) && gasValues.gasPrice;
++ const newGasPrice = gasPriceFromValues && validateMinimumIncrease(gasPriceFromValues, minGasPrice) || minGasPrice;
++ const existingMaxFeePerGas = transactionMeta.txParams?.maxFeePerGas;
++ const minMaxFeePerGas = getIncreasedPriceFromExisting(
++ existingMaxFeePerGas,
++ SPEED_UP_RATE
++ );
++ const maxFeePerGasValues = isFeeMarketEIP1559Values(gasValues) && gasValues.maxFeePerGas;
++ const newMaxFeePerGas = maxFeePerGasValues && validateMinimumIncrease(maxFeePerGasValues, minMaxFeePerGas) || existingMaxFeePerGas && minMaxFeePerGas;
++ const existingMaxPriorityFeePerGas = transactionMeta.txParams?.maxPriorityFeePerGas;
++ const minMaxPriorityFeePerGas = getIncreasedPriceFromExisting(
++ existingMaxPriorityFeePerGas,
++ SPEED_UP_RATE
++ );
++ const maxPriorityFeePerGasValues = isFeeMarketEIP1559Values(gasValues) && gasValues.maxPriorityFeePerGas;
++ const newMaxPriorityFeePerGas = maxPriorityFeePerGasValues && validateMinimumIncrease(
++ maxPriorityFeePerGasValues,
++ minMaxPriorityFeePerGas
++ ) || existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas;
++ const txParams = newMaxFeePerGas && newMaxPriorityFeePerGas ? {
++ ...transactionMeta.txParams,
++ gasLimit: transactionMeta.txParams.gas,
++ maxFeePerGas: newMaxFeePerGas,
++ maxPriorityFeePerGas: newMaxPriorityFeePerGas,
++ type: "0x2" /* feeMarket */
++ } : {
++ ...transactionMeta.txParams,
++ gasLimit: transactionMeta.txParams.gas,
++ gasPrice: newGasPrice
++ };
++ const unsignedEthTx = this.prepareUnsignedEthTx(
++ transactionMeta.chainId,
++ txParams
++ );
++ const signedTx = await this.sign(
++ unsignedEthTx,
++ transactionMeta.txParams.from
++ );
++ const transactionMetaWithRsv = this.updateTransactionMetaRSV(
++ transactionMeta,
++ signedTx
++ );
++ const rawTx = bufferToHex(signedTx.serialize());
++ const newFee = txParams.maxFeePerGas ?? txParams.gasPrice;
++ const oldFee = txParams.maxFeePerGas ? transactionMetaWithRsv.txParams.maxFeePerGas : transactionMetaWithRsv.txParams.gasPrice;
++ projectLogger("Submitting speed up transaction", { oldFee, newFee, txParams });
++ const ethQuery = __privateGet(this, _multichainTrackingHelper).getEthQuery({
++ networkClientId: transactionMeta.networkClientId,
++ chainId: transactionMeta.chainId
++ });
++ const hash = await this.publishTransactionForRetry(
++ ethQuery,
++ rawTx,
++ transactionMeta
++ );
++ const baseTransactionMeta = {
++ ...transactionMetaWithRsv,
++ estimatedBaseFee,
++ id: random(),
++ time: Date.now(),
++ hash,
++ actionId,
++ originalGasEstimate: transactionMeta.txParams.gas,
++ type: "retry" /* retry */,
++ originalType: transactionMeta.type
++ };
++ const newTransactionMeta = newMaxFeePerGas && newMaxPriorityFeePerGas ? {
++ ...baseTransactionMeta,
++ txParams: {
++ ...transactionMeta.txParams,
++ maxFeePerGas: newMaxFeePerGas,
++ maxPriorityFeePerGas: newMaxPriorityFeePerGas
++ }
++ } : {
++ ...baseTransactionMeta,
++ txParams: {
++ ...transactionMeta.txParams,
++ gasPrice: newGasPrice
++ }
++ };
++ this.addMetadata(newTransactionMeta);
++ this.messagingSystem.publish(`${controllerName}:transactionApproved`, {
++ transactionMeta: newTransactionMeta,
++ actionId
++ });
++ this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {
++ transactionMeta: newTransactionMeta,
++ actionId
++ });
++ this.messagingSystem.publish(
++ `${controllerName}:speedupTransactionAdded`,
++ newTransactionMeta
++ );
++ }
++ /**
++ * Estimates required gas for a given transaction.
++ *
++ * @param transaction - The transaction to estimate gas for.
++ * @param networkClientId - The network client id to use for the estimate.
++ * @returns The gas and gas price.
++ */
++ async estimateGas(transaction, networkClientId) {
++ const ethQuery = __privateGet(this, _multichainTrackingHelper).getEthQuery({
++ networkClientId
++ });
++ const { estimatedGas, simulationFails } = await estimateGas(
++ transaction,
++ ethQuery
++ );
++ return { gas: estimatedGas, simulationFails };
++ }
++ /**
++ * Estimates required gas for a given transaction and add additional gas buffer with the given multiplier.
++ *
++ * @param transaction - The transaction params to estimate gas for.
++ * @param multiplier - The multiplier to use for the gas buffer.
++ * @param networkClientId - The network client id to use for the estimate.
++ */
++ async estimateGasBuffered(transaction, multiplier, networkClientId) {
++ const ethQuery = __privateGet(this, _multichainTrackingHelper).getEthQuery({
++ networkClientId
++ });
++ const { blockGasLimit, estimatedGas, simulationFails } = await estimateGas(
++ transaction,
++ ethQuery
++ );
++ const gas = addGasBuffer(estimatedGas, blockGasLimit, multiplier);
++ return {
++ gas,
++ simulationFails
++ };
++ }
++ /**
++ * Updates an existing transaction in state.
++ *
++ * @param transactionMeta - The new transaction to store in state.
++ * @param note - A note or update reason to include in the transaction history.
++ */
++ updateTransaction(transactionMeta, note) {
++ const { id: transactionId } = transactionMeta;
++ __privateMethod(this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, { transactionId, note }, () => ({
++ ...transactionMeta
++ }));
++ }
++ /**
++ * Update the security alert response for a transaction.
++ *
++ * @param transactionId - ID of the transaction.
++ * @param securityAlertResponse - The new security alert response for the transaction.
++ */
++ updateSecurityAlertResponse(transactionId, securityAlertResponse) {
++ if (!securityAlertResponse) {
++ throw new Error(
++ "updateSecurityAlertResponse: securityAlertResponse should not be null"
++ );
++ }
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ throw new Error(
++ `Cannot update security alert response as no transaction metadata found`
++ );
++ }
++ const updatedTransactionMeta = {
++ ...transactionMeta,
++ securityAlertResponse
++ };
++ this.updateTransaction(
++ updatedTransactionMeta,
++ `${controllerName}:updatesecurityAlertResponse - securityAlertResponse updated`
++ );
++ }
++ /**
++ * Removes all transactions from state, optionally based on the current network.
++ *
++ * @param ignoreNetwork - Determines whether to wipe all transactions, or just those on the
++ * current network. If `true`, all transactions are wiped.
++ * @param address - If specified, only transactions originating from this address will be
++ * wiped on current network.
++ */
++ wipeTransactions(ignoreNetwork, address) {
++ if (ignoreNetwork && !address) {
++ this.update((state) => {
++ state.transactions = [];
++ });
++ return;
++ }
++ const currentChainId = this.getChainId();
++ const newTransactions = this.state.transactions.filter(
++ ({ chainId, txParams }) => {
++ const isMatchingNetwork = ignoreNetwork || chainId === currentChainId;
++ if (!isMatchingNetwork) {
++ return true;
++ }
++ const isMatchingAddress = !address || txParams.from?.toLowerCase() === address.toLowerCase();
++ return !isMatchingAddress;
++ }
++ );
++ this.update((state) => {
++ state.transactions = this.trimTransactionsForState(newTransactions);
++ });
++ }
++ /**
++ * Adds external provided transaction to state as confirmed transaction.
++ *
++ * @param transactionMeta - TransactionMeta to add transactions.
++ * @param transactionReceipt - TransactionReceipt of the external transaction.
++ * @param baseFeePerGas - Base fee per gas of the external transaction.
++ */
++ async confirmExternalTransaction(transactionMeta, transactionReceipt, baseFeePerGas) {
++ const newTransactionMeta = this.addExternalTransaction(transactionMeta);
++ try {
++ const transactionId = newTransactionMeta.id;
++ const updatedTransactionMeta = {
++ ...newTransactionMeta,
++ status: "confirmed" /* confirmed */,
++ txReceipt: transactionReceipt
++ };
++ if (baseFeePerGas) {
++ updatedTransactionMeta.baseFeePerGas = baseFeePerGas;
++ }
++ this.markNonceDuplicatesDropped(transactionId);
++ this.updateTransaction(
++ updatedTransactionMeta,
++ `${controllerName}:confirmExternalTransaction - Add external transaction`
++ );
++ this.onTransactionStatusChange(updatedTransactionMeta);
++ this.updatePostBalance(updatedTransactionMeta);
++ this.messagingSystem.publish(
++ `${controllerName}:transactionConfirmed`,
++ updatedTransactionMeta
++ );
++ } catch (error) {
++ console.error("Failed to confirm external transaction", error);
++ }
++ }
++ /**
++ * Append new send flow history to a transaction.
++ *
++ * @param transactionID - The ID of the transaction to update.
++ * @param currentSendFlowHistoryLength - The length of the current sendFlowHistory array.
++ * @param sendFlowHistoryToAdd - The sendFlowHistory entries to add.
++ * @returns The updated transactionMeta.
++ */
++ updateTransactionSendFlowHistory(transactionID, currentSendFlowHistoryLength, sendFlowHistoryToAdd) {
++ if (this.isSendFlowHistoryDisabled) {
++ throw new Error(
++ "Send flow history is disabled for the current transaction controller"
++ );
++ }
++ const transactionMeta = this.getTransaction(transactionID);
++ if (!transactionMeta) {
++ throw new Error(
++ `Cannot update send flow history as no transaction metadata found`
++ );
++ }
++ validateIfTransactionUnapproved(
++ transactionMeta,
++ "updateTransactionSendFlowHistory"
++ );
++ const sendFlowHistory = transactionMeta.sendFlowHistory ?? [];
++ if (currentSendFlowHistoryLength === sendFlowHistory.length) {
++ const updatedTransactionMeta = {
++ ...transactionMeta,
++ sendFlowHistory: [...sendFlowHistory, ...sendFlowHistoryToAdd]
++ };
++ this.updateTransaction(
++ updatedTransactionMeta,
++ `${controllerName}:updateTransactionSendFlowHistory - sendFlowHistory updated`
++ );
++ }
++ return this.getTransaction(transactionID);
++ }
++ /**
++ * Update the gas values of a transaction.
++ *
++ * @param transactionId - The ID of the transaction to update.
++ * @param gasValues - Gas values to update.
++ * @param gasValues.gas - Same as transaction.gasLimit.
++ * @param gasValues.gasLimit - Maxmimum number of units of gas to use for this transaction.
++ * @param gasValues.gasPrice - Price per gas for legacy transactions.
++ * @param gasValues.maxPriorityFeePerGas - Maximum amount per gas to give to validator as incentive.
++ * @param gasValues.maxFeePerGas - Maximum amount per gas to pay for the transaction, including the priority fee.
++ * @param gasValues.estimateUsed - Which estimate level was used.
++ * @param gasValues.estimateSuggested - Which estimate level that the API suggested.
++ * @param gasValues.defaultGasEstimates - The default estimate for gas.
++ * @param gasValues.originalGasEstimate - Original estimate for gas.
++ * @param gasValues.userEditedGasLimit - The gas limit supplied by user.
++ * @param gasValues.userFeeLevel - Estimate level user selected.
++ * @returns The updated transactionMeta.
++ */
++ updateTransactionGasFees(transactionId, {
++ defaultGasEstimates,
++ estimateUsed,
++ estimateSuggested,
++ gas,
++ gasLimit,
++ gasPrice,
++ maxPriorityFeePerGas,
++ maxFeePerGas,
++ originalGasEstimate,
++ userEditedGasLimit,
++ userFeeLevel
++ }) {
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ throw new Error(
++ `Cannot update transaction as no transaction metadata found`
++ );
++ }
++ validateIfTransactionUnapproved(
++ transactionMeta,
++ "updateTransactionGasFees"
++ );
++ let transactionGasFees = {
++ txParams: {
++ gas,
++ gasLimit,
++ gasPrice,
++ maxPriorityFeePerGas,
++ maxFeePerGas
++ },
++ defaultGasEstimates,
++ estimateUsed,
++ estimateSuggested,
++ originalGasEstimate,
++ userEditedGasLimit,
++ userFeeLevel
++ // TODO: Replace `any` with type
++ // eslint-disable-next-line @typescript-eslint/no-explicit-any
++ };
++ transactionGasFees.txParams = pickBy(transactionGasFees.txParams);
++ transactionGasFees = pickBy(transactionGasFees);
++ const updatedMeta = merge({}, transactionMeta, transactionGasFees);
++ this.updateTransaction(
++ updatedMeta,
++ `${controllerName}:updateTransactionGasFees - gas values updated`
++ );
++ return this.getTransaction(transactionId);
++ }
++ /**
++ * Update the previous gas values of a transaction.
++ *
++ * @param transactionId - The ID of the transaction to update.
++ * @param previousGas - Previous gas values to update.
++ * @param previousGas.gasLimit - Maxmimum number of units of gas to use for this transaction.
++ * @param previousGas.maxFeePerGas - Maximum amount per gas to pay for the transaction, including the priority fee.
++ * @param previousGas.maxPriorityFeePerGas - Maximum amount per gas to give to validator as incentive.
++ * @returns The updated transactionMeta.
++ */
++ updatePreviousGasParams(transactionId, {
++ gasLimit,
++ maxFeePerGas,
++ maxPriorityFeePerGas
++ }) {
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ throw new Error(
++ `Cannot update transaction as no transaction metadata found`
++ );
++ }
++ validateIfTransactionUnapproved(transactionMeta, "updatePreviousGasParams");
++ const transactionPreviousGas = {
++ previousGas: {
++ gasLimit,
++ maxFeePerGas,
++ maxPriorityFeePerGas
++ }
++ // TODO: Replace `any` with type
++ // eslint-disable-next-line @typescript-eslint/no-explicit-any
++ };
++ transactionPreviousGas.previousGas = pickBy(
++ transactionPreviousGas.previousGas
++ );
++ const updatedMeta = merge({}, transactionMeta, transactionPreviousGas);
++ this.updateTransaction(
++ updatedMeta,
++ `${controllerName}:updatePreviousGasParams - Previous gas values updated`
++ );
++ return this.getTransaction(transactionId);
++ }
++ async getNonceLock(address, networkClientId) {
++ return __privateGet(this, _multichainTrackingHelper).getNonceLock(
++ address,
++ networkClientId
++ );
++ }
++ /**
++ * Updates the editable parameters of a transaction.
++ *
++ * @param txId - The ID of the transaction to update.
++ * @param params - The editable parameters to update.
++ * @param params.data - Data to pass with the transaction.
++ * @param params.gas - Maximum number of units of gas to use for the transaction.
++ * @param params.gasPrice - Price per gas for legacy transactions.
++ * @param params.from - Address to send the transaction from.
++ * @param params.to - Address to send the transaction to.
++ * @param params.value - Value associated with the transaction.
++ * @returns The updated transaction metadata.
++ */
++ async updateEditableParams(txId, {
++ data,
++ gas,
++ gasPrice,
++ from,
++ to,
++ value
++ }) {
++ const transactionMeta = this.getTransaction(txId);
++ if (!transactionMeta) {
++ throw new Error(
++ `Cannot update editable params as no transaction metadata found`
++ );
++ }
++ validateIfTransactionUnapproved(transactionMeta, "updateEditableParams");
++ const editableParams = {
++ txParams: {
++ data,
++ from,
++ to,
++ value,
++ gas,
++ gasPrice
++ }
++ };
++ editableParams.txParams = pickBy(
++ editableParams.txParams
++ );
++ const updatedTransaction = merge({}, transactionMeta, editableParams);
++ const provider = __privateGet(this, _multichainTrackingHelper).getProvider({
++ chainId: transactionMeta.chainId,
++ networkClientId: transactionMeta.networkClientId
++ });
++ const ethQuery = new EthQuery(provider);
++ const { type } = await determineTransactionType(
++ updatedTransaction.txParams,
++ ethQuery
++ );
++ updatedTransaction.type = type;
++ await updateTransactionLayer1GasFee({
++ layer1GasFeeFlows: this.layer1GasFeeFlows,
++ provider,
++ transactionMeta: updatedTransaction
++ });
++ this.updateTransaction(
++ updatedTransaction,
++ `Update Editable Params for ${txId}`
++ );
++ return this.getTransaction(txId);
++ }
++ /**
++ * Signs and returns the raw transaction data for provided transaction params list.
++ *
++ * @param listOfTxParams - The list of transaction params to approve.
++ * @param opts - Options bag.
++ * @param opts.hasNonce - Whether the transactions already have a nonce.
++ * @returns The raw transactions.
++ */
++ async approveTransactionsWithSameNonce(listOfTxParams = [], { hasNonce } = {}) {
++ projectLogger("Approving transactions with same nonce", {
++ transactions: listOfTxParams
++ });
++ if (listOfTxParams.length === 0) {
++ return "";
++ }
++ const initialTx = listOfTxParams[0];
++ const common = this.getCommonConfiguration(initialTx.chainId);
++ let networkClientId;
++ try {
++ networkClientId = this.messagingSystem.call(
++ `NetworkController:findNetworkClientIdByChainId`,
++ initialTx.chainId
++ );
++ } catch (err) {
++ projectLogger("failed to find networkClientId from chainId", err);
++ }
++ const initialTxAsEthTx = TransactionFactory.fromTxData(initialTx, {
++ common
++ });
++ const initialTxAsSerializedHex = bufferToHex(initialTxAsEthTx.serialize());
++ if (this.approvingTransactionIds.has(initialTxAsSerializedHex)) {
++ return "";
++ }
++ this.approvingTransactionIds.add(initialTxAsSerializedHex);
++ let rawTransactions, nonceLock;
++ try {
++ const fromAddress = initialTx.from;
++ const requiresNonce = hasNonce !== true;
++ nonceLock = requiresNonce ? await this.getNonceLock(fromAddress, networkClientId) : void 0;
++ const nonce = nonceLock ? add0x(nonceLock.nextNonce.toString(16)) : initialTx.nonce;
++ if (nonceLock) {
++ projectLogger("Using nonce from nonce tracker", nonce, nonceLock.nonceDetails);
++ }
++ rawTransactions = await Promise.all(
++ listOfTxParams.map((txParams) => {
++ txParams.nonce = nonce;
++ return this.signExternalTransaction(txParams.chainId, txParams);
++ })
++ );
++ } catch (err) {
++ projectLogger("Error while signing transactions with same nonce", err);
++ throw err;
++ } finally {
++ nonceLock?.releaseLock();
++ this.approvingTransactionIds.delete(initialTxAsSerializedHex);
++ }
++ return rawTransactions;
++ }
++ /**
++ * Update a custodial transaction.
++ *
++ * @param transactionId - The ID of the transaction to update.
++ * @param options - The custodial transaction options to update.
++ * @param options.errorMessage - The error message to be assigned in case transaction status update to failed.
++ * @param options.hash - The new hash value to be assigned.
++ * @param options.status - The new status value to be assigned.
++ */
++ updateCustodialTransaction(transactionId, {
++ errorMessage,
++ hash,
++ status
++ }) {
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ throw new Error(
++ `Cannot update custodial transaction as no transaction metadata found`
++ );
++ }
++ if (!transactionMeta.custodyId) {
++ throw new Error("Transaction must be a custodian transaction");
++ }
++ if (status && ![
++ "submitted" /* submitted */,
++ "signed" /* signed */,
++ "failed" /* failed */
++ ].includes(status)) {
++ throw new Error(
++ `Cannot update custodial transaction with status: ${status}`
++ );
++ }
++ const updatedTransactionMeta = merge(
++ {},
++ transactionMeta,
++ pickBy({ hash, status })
++ );
++ if (updatedTransactionMeta.status === "submitted" /* submitted */) {
++ updatedTransactionMeta.submittedTime = (/* @__PURE__ */ new Date()).getTime();
++ }
++ if (updatedTransactionMeta.status === "failed" /* failed */) {
++ updatedTransactionMeta.error = normalizeTxError(new Error(errorMessage));
++ }
++ this.updateTransaction(
++ updatedTransactionMeta,
++ `${controllerName}:updateCustodialTransaction - Custodial transaction updated`
++ );
++ if (["submitted" /* submitted */, "failed" /* failed */].includes(
++ status
++ )) {
++ this.messagingSystem.publish(
++ `${controllerName}:transactionFinished`,
++ updatedTransactionMeta
++ );
++ __privateGet(this, _internalEvents).emit(
++ `${updatedTransactionMeta.id}:finished`,
++ updatedTransactionMeta
++ );
++ }
++ }
++ /**
++ * Search transaction metadata for matching entries.
++ *
++ * @param opts - Options bag.
++ * @param opts.searchCriteria - An object containing values or functions for transaction properties to filter transactions with.
++ * @param opts.initialList - The transactions to search. Defaults to the current state.
++ * @param opts.filterToCurrentNetwork - Whether to filter the results to the current network. Defaults to true.
++ * @param opts.limit - The maximum number of transactions to return. No limit by default.
++ * @returns An array of transactions matching the provided options.
++ */
++ getTransactions({
++ searchCriteria = {},
++ initialList,
++ filterToCurrentNetwork = true,
++ limit
++ } = {}) {
++ const chainId = this.getChainId();
++ const predicateMethods = mapValues(searchCriteria, (predicate) => {
++ return typeof predicate === "function" ? predicate : (
++ // TODO: Replace `any` with type
++ // eslint-disable-next-line @typescript-eslint/no-explicit-any
++ (v) => v === predicate
++ );
++ });
++ const transactionsToFilter = initialList ?? this.state.transactions;
++ const filteredTransactions = sortBy(
++ pickBy(transactionsToFilter, (transaction) => {
++ if (filterToCurrentNetwork && transaction.chainId !== chainId) {
++ return false;
++ }
++ for (const [key, predicate] of Object.entries(predicateMethods)) {
++ if (key in transaction.txParams) {
++ if (predicate(transaction.txParams[key]) === false) {
++ return false;
++ }
++ } else if (predicate(transaction[key]) === false) {
++ return false;
++ }
++ }
++ return true;
++ }),
++ "time"
++ );
++ if (limit !== void 0) {
++ const nonces = /* @__PURE__ */ new Set();
++ const txs = [];
++ for (let i = filteredTransactions.length - 1; i > -1; i--) {
++ const txMeta = filteredTransactions[i];
++ const { nonce } = txMeta.txParams;
++ if (!nonces.has(nonce)) {
++ if (nonces.size < limit) {
++ nonces.add(nonce);
++ } else {
++ continue;
++ }
++ }
++ txs.unshift(txMeta);
++ }
++ return txs;
++ }
++ return filteredTransactions;
++ }
++ async estimateGasFee({
++ transactionParams,
++ chainId,
++ networkClientId: requestNetworkClientId
++ }) {
++ const networkClientId = __privateMethod(this, _getNetworkClientId, getNetworkClientId_fn).call(this, {
++ networkClientId: requestNetworkClientId,
++ chainId
++ });
++ const transactionMeta = {
++ txParams: transactionParams,
++ chainId,
++ networkClientId
++ };
++ const gasFeeFlow = getGasFeeFlow(
++ transactionMeta,
++ this.gasFeeFlows
++ );
++ const ethQuery = __privateGet(this, _multichainTrackingHelper).getEthQuery({
++ networkClientId,
++ chainId
++ });
++ const gasFeeControllerData = await this.getGasFeeEstimates({
++ networkClientId
++ });
++ return gasFeeFlow.getGasFees({
++ ethQuery,
++ gasFeeControllerData,
++ transactionMeta
++ });
++ }
++ /**
++ * Determine the layer 1 gas fee for the given transaction parameters.
++ *
++ * @param request - The request object.
++ * @param request.transactionParams - The transaction parameters to estimate the layer 1 gas fee for.
++ * @param request.chainId - The ID of the chain where the transaction will be executed.
++ * @param request.networkClientId - The ID of a specific network client to process the transaction.
++ */
++ async getLayer1GasFee({
++ transactionParams,
++ chainId,
++ networkClientId
++ }) {
++ const provider = __privateGet(this, _multichainTrackingHelper).getProvider({
++ networkClientId,
++ chainId
++ });
++ return await getTransactionLayer1GasFee({
++ layer1GasFeeFlows: this.layer1GasFeeFlows,
++ provider,
++ transactionMeta: {
++ txParams: transactionParams,
++ chainId
++ }
++ });
++ }
++ async signExternalTransaction(chainId, transactionParams) {
++ if (!this.sign) {
++ throw new Error("No sign method defined.");
++ }
++ const normalizedTransactionParams = normalizeTransactionParams(transactionParams);
++ const type = isEIP1559Transaction(normalizedTransactionParams) ? "0x2" /* feeMarket */ : "0x0" /* legacy */;
++ const updatedTransactionParams = {
++ ...normalizedTransactionParams,
++ type,
++ gasLimit: normalizedTransactionParams.gas,
++ chainId
++ };
++ const { from } = updatedTransactionParams;
++ const common = this.getCommonConfiguration(chainId);
++ const unsignedTransaction = TransactionFactory.fromTxData(
++ updatedTransactionParams,
++ { common }
++ );
++ const signedTransaction = await this.sign(unsignedTransaction, from);
++ const rawTransaction = bufferToHex(signedTransaction.serialize());
++ return rawTransaction;
++ }
++ /**
++ * Removes unapproved transactions from state.
++ */
++ clearUnapprovedTransactions() {
++ const transactions = this.state.transactions.filter(
++ ({ status }) => status !== "unapproved" /* unapproved */
++ );
++ this.update((state) => {
++ state.transactions = this.trimTransactionsForState(transactions);
++ });
++ }
++ /**
++ * Stop the signing process for a specific transaction.
++ * Throws an error causing the transaction status to be set to failed.
++ * @param transactionId - The ID of the transaction to stop signing.
++ */
++ abortTransactionSigning(transactionId) {
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ throw new Error(`Cannot abort signing as no transaction metadata found`);
++ }
++ const abortCallback = this.signAbortCallbacks.get(transactionId);
++ if (!abortCallback) {
++ throw new Error(
++ `Cannot abort signing as transaction is not waiting for signing`
++ );
++ }
++ abortCallback();
++ this.signAbortCallbacks.delete(transactionId);
++ }
++ addMetadata(transactionMeta) {
++ this.update((state) => {
++ state.transactions = this.trimTransactionsForState([
++ ...state.transactions,
++ transactionMeta
++ ]);
++ });
++ }
++ async updateGasProperties(transactionMeta) {
++ const isEIP1559Compatible = await this.getEIP1559Compatibility(transactionMeta.networkClientId) && transactionMeta.txParams.type !== "0x0" /* legacy */;
++ const { networkClientId, chainId } = transactionMeta;
++ const isCustomNetwork = __privateMethod(this, _isCustomNetwork, isCustomNetwork_fn).call(this, networkClientId);
++ const ethQuery = __privateGet(this, _multichainTrackingHelper).getEthQuery({
++ networkClientId,
++ chainId
++ });
++ const provider = __privateGet(this, _multichainTrackingHelper).getProvider({
++ networkClientId,
++ chainId
++ });
++ await updateGas({
++ ethQuery,
++ chainId,
++ isCustomNetwork,
++ txMeta: transactionMeta
++ });
++ await updateGasFees({
++ eip1559: isEIP1559Compatible,
++ ethQuery,
++ gasFeeFlows: this.gasFeeFlows,
++ getGasFeeEstimates: this.getGasFeeEstimates,
++ getSavedGasFees: this.getSavedGasFees.bind(this),
++ txMeta: transactionMeta
++ });
++ await updateTransactionLayer1GasFee({
++ layer1GasFeeFlows: this.layer1GasFeeFlows,
++ provider,
++ transactionMeta
++ });
++ }
++ onBootCleanup() {
++ this.clearUnapprovedTransactions();
++ this.failIncompleteTransactions();
++ }
++ failIncompleteTransactions() {
++ const incompleteTransactions = this.state.transactions.filter(
++ (transaction) => ["approved" /* approved */, "signed" /* signed */].includes(
++ transaction.status
++ )
++ );
++ for (const transactionMeta of incompleteTransactions) {
++ this.failTransaction(
++ transactionMeta,
++ new Error("Transaction incomplete at startup")
++ );
++ }
++ }
++ async processApproval(transactionMeta, {
++ isExisting = false,
++ requireApproval,
++ shouldShowRequest = true,
++ actionId
++ }) {
++ const transactionId = transactionMeta.id;
++ let resultCallbacks;
++ const { meta, isCompleted } = this.isTransactionCompleted(transactionId);
++ const finishedPromise = isCompleted ? Promise.resolve(meta) : this.waitForTransactionFinished(transactionId);
++ if (meta && !isExisting && !isCompleted) {
++ try {
++ if (requireApproval !== false) {
++ const acceptResult = await this.requestApproval(transactionMeta, {
++ shouldShowRequest
++ });
++ resultCallbacks = acceptResult.resultCallbacks;
++ const approvalValue = acceptResult.value;
++ const updatedTransaction = approvalValue?.txMeta;
++ if (updatedTransaction) {
++ projectLogger("Updating transaction with approval data", {
++ customNonce: updatedTransaction.customNonceValue,
++ params: updatedTransaction.txParams
++ });
++ this.updateTransaction(
++ updatedTransaction,
++ "TransactionController#processApproval - Updated with approval data"
++ );
++ }
++ }
++ const { isCompleted: isTxCompleted } = this.isTransactionCompleted(transactionId);
++ if (!isTxCompleted) {
++ const approvalResult = await this.approveTransaction(transactionId);
++ if (approvalResult === "skipped-via-before-publish-hook" /* SkippedViaBeforePublishHook */ && resultCallbacks) {
++ resultCallbacks.success();
++ }
++ const updatedTransactionMeta = this.getTransaction(
++ transactionId
++ );
++ this.messagingSystem.publish(
++ `${controllerName}:transactionApproved`,
++ {
++ transactionMeta: updatedTransactionMeta,
++ actionId
++ }
++ );
++ }
++ } catch (error) {
++ const { isCompleted: isTxCompleted } = this.isTransactionCompleted(transactionId);
++ if (!isTxCompleted) {
++ if (error?.code === errorCodes.provider.userRejectedRequest) {
++ this.cancelTransaction(transactionId, actionId);
++ throw providerErrors.userRejectedRequest(
++ "MetaMask Tx Signature: User denied transaction signature."
++ );
++ } else {
++ this.failTransaction(meta, error, actionId);
++ }
++ }
++ }
++ }
++ const finalMeta = await finishedPromise;
++ switch (finalMeta?.status) {
++ case "failed" /* failed */:
++ resultCallbacks?.error(finalMeta.error);
++ throw rpcErrors.internal(finalMeta.error.message);
++ case "submitted" /* submitted */:
++ resultCallbacks?.success();
++ return finalMeta.hash;
++ default:
++ const internalError = rpcErrors.internal(
++ `MetaMask Tx Signature: Unknown problem: ${JSON.stringify(
++ finalMeta || transactionId
++ )}`
++ );
++ resultCallbacks?.error(internalError);
++ throw internalError;
++ }
++ }
++ /**
++ * Approves a transaction and updates it's status in state. If this is not a
++ * retry transaction, a nonce will be generated. The transaction is signed
++ * using the sign configuration property, then published to the blockchain.
++ * A `:finished` hub event is fired after success or failure.
++ *
++ * @param transactionId - The ID of the transaction to approve.
++ */
++ async approveTransaction(transactionId) {
++ const cleanupTasks = new Array();
++ cleanupTasks.push(await this.mutex.acquire());
++ let transactionMeta = this.getTransactionOrThrow(transactionId);
++ try {
++ if (!this.sign) {
++ this.failTransaction(
++ transactionMeta,
++ new Error("No sign method defined.")
++ );
++ return "not-approved" /* NotApproved */;
++ } else if (!transactionMeta.chainId) {
++ this.failTransaction(transactionMeta, new Error("No chainId defined."));
++ return "not-approved" /* NotApproved */;
++ }
++ if (this.approvingTransactionIds.has(transactionId)) {
++ projectLogger("Skipping approval as signing in progress", transactionId);
++ return "not-approved" /* NotApproved */;
++ }
++ this.approvingTransactionIds.add(transactionId);
++ cleanupTasks.push(
++ () => this.approvingTransactionIds.delete(transactionId)
++ );
++ const [nonce, releaseNonce] = await getNextNonce(
++ transactionMeta,
++ (address) => __privateGet(this, _multichainTrackingHelper).getNonceLock(
++ address,
++ transactionMeta.networkClientId
++ )
++ );
++ releaseNonce && cleanupTasks.push(releaseNonce);
++ transactionMeta = __privateMethod(this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, {
++ transactionId,
++ note: "TransactionController#approveTransaction - Transaction approved"
++ }, (draftTxMeta) => {
++ const { txParams, chainId } = draftTxMeta;
++ draftTxMeta.status = "approved" /* approved */;
++ draftTxMeta.txParams = {
++ ...txParams,
++ nonce,
++ chainId,
++ gasLimit: txParams.gas,
++ ...isEIP1559Transaction(txParams) && {
++ type: "0x2" /* feeMarket */
++ }
++ };
++ });
++ this.onTransactionStatusChange(transactionMeta);
++ const rawTx = await this.signTransaction(
++ transactionMeta,
++ transactionMeta.txParams
++ );
++ if (!this.beforePublish(transactionMeta)) {
++ projectLogger("Skipping publishing transaction based on hook");
++ this.messagingSystem.publish(
++ `${controllerName}:transactionPublishingSkipped`,
++ transactionMeta
++ );
++ return "skipped-via-before-publish-hook" /* SkippedViaBeforePublishHook */;
++ }
++ if (!rawTx) {
++ return "not-approved" /* NotApproved */;
++ }
++ const ethQuery = __privateGet(this, _multichainTrackingHelper).getEthQuery({
++ networkClientId: transactionMeta.networkClientId,
++ chainId: transactionMeta.chainId
++ });
++ let preTxBalance;
++ const shouldUpdatePreTxBalance = transactionMeta.type === "swap" /* swap */;
++ if (shouldUpdatePreTxBalance) {
++ projectLogger("Determining pre-transaction balance");
++ preTxBalance = await query(ethQuery, "getBalance", [
++ transactionMeta.txParams.from
++ ]);
++ }
++ projectLogger("Publishing transaction", transactionMeta.txParams);
++ let { transactionHash: hash } = await this.publish(
++ transactionMeta,
++ rawTx
++ );
++ if (hash === void 0) {
++ hash = await this.publishTransaction(ethQuery, rawTx);
++ }
++ projectLogger("Publish successful", hash);
++ transactionMeta = __privateMethod(this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, {
++ transactionId,
++ note: "TransactionController#approveTransaction - Transaction submitted"
++ }, (draftTxMeta) => {
++ draftTxMeta.hash = hash;
++ draftTxMeta.status = "submitted" /* submitted */;
++ draftTxMeta.submittedTime = (/* @__PURE__ */ new Date()).getTime();
++ if (shouldUpdatePreTxBalance) {
++ draftTxMeta.preTxBalance = preTxBalance;
++ projectLogger("Updated pre-transaction balance", preTxBalance);
++ }
++ });
++ this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {
++ transactionMeta
++ });
++ this.messagingSystem.publish(
++ `${controllerName}:transactionFinished`,
++ transactionMeta
++ );
++ __privateGet(this, _internalEvents).emit(`${transactionId}:finished`, transactionMeta);
++ this.onTransactionStatusChange(transactionMeta);
++ return "approved" /* Approved */;
++ } catch (error) {
++ this.failTransaction(transactionMeta, error);
++ return "not-approved" /* NotApproved */;
++ } finally {
++ cleanupTasks.forEach((task) => task());
++ }
++ }
++ async publishTransaction(ethQuery, rawTransaction) {
++ return await query(ethQuery, "sendRawTransaction", [rawTransaction]);
++ }
++ /**
++ * Cancels a transaction based on its ID by setting its status to "rejected"
++ * and emitting a `:finished` hub event.
++ *
++ * @param transactionId - The ID of the transaction to cancel.
++ * @param actionId - The actionId passed from UI
++ */
++ cancelTransaction(transactionId, actionId) {
++ const transactionMeta = this.state.transactions.find(
++ ({ id }) => id === transactionId
++ );
++ if (!transactionMeta) {
++ return;
++ }
++ this.update((state) => {
++ const transactions = state.transactions.filter(
++ ({ id }) => id !== transactionId
++ );
++ state.transactions = this.trimTransactionsForState(transactions);
++ });
++ const updatedTransactionMeta = {
++ ...transactionMeta,
++ status: "rejected" /* rejected */
++ };
++ this.messagingSystem.publish(
++ `${controllerName}:transactionFinished`,
++ updatedTransactionMeta
++ );
++ __privateGet(this, _internalEvents).emit(
++ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
++ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
++ `${transactionMeta.id}:finished`,
++ updatedTransactionMeta
++ );
++ this.messagingSystem.publish(`${controllerName}:transactionRejected`, {
++ transactionMeta: updatedTransactionMeta,
++ actionId
++ });
++ this.onTransactionStatusChange(updatedTransactionMeta);
++ }
++ /**
++ * Trim the amount of transactions that are set on the state. Checks
++ * if the length of the tx history is longer then desired persistence
++ * limit and then if it is removes the oldest confirmed or rejected tx.
++ * Pending or unapproved transactions will not be removed by this
++ * operation. For safety of presenting a fully functional transaction UI
++ * representation, this function will not break apart transactions with the
++ * same nonce, created on the same day, per network. Not accounting for
++ * transactions of the same nonce, same day and network combo can result in
++ * confusing or broken experiences in the UI.
++ *
++ * @param transactions - The transactions to be applied to the state.
++ * @returns The trimmed list of transactions.
++ */
++ trimTransactionsForState(transactions) {
++ const nonceNetworkSet = /* @__PURE__ */ new Set();
++ const txsToKeep = [...transactions].sort((a, b) => a.time > b.time ? -1 : 1).filter((tx) => {
++ const { chainId, status, txParams, time } = tx;
++ if (txParams) {
++ const key = `${String(txParams.nonce)}-${convertHexToDecimal(
++ chainId
++ )}-${new Date(time).toDateString()}`;
++ if (nonceNetworkSet.has(key)) {
++ return true;
++ } else if (nonceNetworkSet.size < __privateGet(this, _transactionHistoryLimit) || !this.isFinalState(status)) {
++ nonceNetworkSet.add(key);
++ return true;
++ }
++ }
++ return false;
++ });
++ txsToKeep.reverse();
++ return txsToKeep;
++ }
++ /**
++ * Determines if the transaction is in a final state.
++ *
++ * @param status - The transaction status.
++ * @returns Whether the transaction is in a final state.
++ */
++ isFinalState(status) {
++ return status === "rejected" /* rejected */ || status === "confirmed" /* confirmed */ || status === "failed" /* failed */;
++ }
++ /**
++ * Whether the transaction has at least completed all local processing.
++ *
++ * @param status - The transaction status.
++ * @returns Whether the transaction is in a final state.
++ */
++ isLocalFinalState(status) {
++ return [
++ "confirmed" /* confirmed */,
++ "failed" /* failed */,
++ "rejected" /* rejected */,
++ "submitted" /* submitted */
++ ].includes(status);
++ }
++ async requestApproval(txMeta, { shouldShowRequest }) {
++ const id = this.getApprovalId(txMeta);
++ const { origin } = txMeta;
++ const type = ApprovalType.Transaction;
++ const requestData = { txId: txMeta.id };
++ return await this.messagingSystem.call(
++ "ApprovalController:addRequest",
++ {
++ id,
++ origin: origin || ORIGIN_METAMASK,
++ type,
++ requestData,
++ expectsResult: true
++ },
++ shouldShowRequest
++ );
++ }
++ getTransaction(transactionId) {
++ const { transactions } = this.state;
++ return transactions.find(({ id }) => id === transactionId);
++ }
++ getTransactionOrThrow(transactionId, errorMessagePrefix = "TransactionController") {
++ const txMeta = this.getTransaction(transactionId);
++ if (!txMeta) {
++ throw new Error(
++ `${errorMessagePrefix}: No transaction found with id ${transactionId}`
++ );
++ }
++ return txMeta;
++ }
++ getApprovalId(txMeta) {
++ return String(txMeta.id);
++ }
++ isTransactionCompleted(transactionId) {
++ const transaction = this.getTransaction(transactionId);
++ if (!transaction) {
++ return { meta: void 0, isCompleted: false };
++ }
++ const isCompleted = this.isLocalFinalState(transaction.status);
++ return { meta: transaction, isCompleted };
++ }
++ getChainId(networkClientId) {
++ const globalChainId = __privateMethod(this, _getGlobalChainId, getGlobalChainId_fn).call(this);
++ const globalNetworkClientId = __privateMethod(this, _getGlobalNetworkClientId, getGlobalNetworkClientId_fn).call(this);
++ if (!networkClientId || networkClientId === globalNetworkClientId) {
++ return globalChainId;
++ }
++ return this.messagingSystem.call(
++ `NetworkController:getNetworkClientById`,
++ networkClientId
++ ).configuration.chainId;
++ }
++ prepareUnsignedEthTx(chainId, txParams) {
++ return TransactionFactory.fromTxData(txParams, {
++ freeze: false,
++ common: this.getCommonConfiguration(chainId)
++ });
++ }
++ /**
++ * `@ethereumjs/tx` uses `@ethereumjs/common` as a configuration tool for
++ * specifying which chain, network, hardfork and EIPs to support for
++ * a transaction. By referencing this configuration, and analyzing the fields
++ * specified in txParams, @ethereumjs/tx is able to determine which EIP-2718
++ * transaction type to use.
++ *
++ * @param chainId - The chainId to use for the configuration.
++ * @returns common configuration object
++ */
++ getCommonConfiguration(chainId) {
++ const customChainParams = {
++ chainId: parseInt(chainId, 16),
++ defaultHardfork: HARDFORK
++ };
++ return Common.custom(customChainParams);
++ }
++ onIncomingTransactions({
++ added,
++ updated
++ }) {
++ this.update((state) => {
++ const { transactions: currentTransactions } = state;
++ const updatedTransactions = [
++ ...added,
++ ...currentTransactions.map((originalTransaction) => {
++ const updatedTransaction = updated.find(
++ ({ hash }) => hash === originalTransaction.hash
++ );
++ return updatedTransaction ?? originalTransaction;
++ })
++ ];
++ state.transactions = this.trimTransactionsForState(updatedTransactions);
++ });
++ }
++ onUpdatedLastFetchedBlockNumbers({
++ lastFetchedBlockNumbers,
++ blockNumber
++ }) {
++ this.update((state) => {
++ state.lastFetchedBlockNumbers = lastFetchedBlockNumbers;
++ });
++ this.messagingSystem.publish(
++ `${controllerName}:incomingTransactionBlockReceived`,
++ blockNumber
++ );
++ }
++ generateDappSuggestedGasFees(txParams, origin) {
++ if (!origin || origin === ORIGIN_METAMASK) {
++ return void 0;
++ }
++ const { gasPrice, maxFeePerGas, maxPriorityFeePerGas, gas } = txParams;
++ if (gasPrice === void 0 && maxFeePerGas === void 0 && maxPriorityFeePerGas === void 0 && gas === void 0) {
++ return void 0;
++ }
++ const dappSuggestedGasFees = {};
++ if (gasPrice !== void 0) {
++ dappSuggestedGasFees.gasPrice = gasPrice;
++ } else if (maxFeePerGas !== void 0 || maxPriorityFeePerGas !== void 0) {
++ dappSuggestedGasFees.maxFeePerGas = maxFeePerGas;
++ dappSuggestedGasFees.maxPriorityFeePerGas = maxPriorityFeePerGas;
++ }
++ if (gas !== void 0) {
++ dappSuggestedGasFees.gas = gas;
++ }
++ return dappSuggestedGasFees;
++ }
++ /**
++ * Validates and adds external provided transaction to state.
++ *
++ * @param transactionMeta - Nominated external transaction to be added to state.
++ * @returns The new transaction.
++ */
++ addExternalTransaction(transactionMeta) {
++ const { chainId } = transactionMeta;
++ const { transactions } = this.state;
++ const fromAddress = transactionMeta?.txParams?.from;
++ const sameFromAndNetworkTransactions = transactions.filter(
++ (transaction) => transaction.txParams.from === fromAddress && transaction.chainId === chainId
++ );
++ const confirmedTxs = sameFromAndNetworkTransactions.filter(
++ (transaction) => transaction.status === "confirmed" /* confirmed */
++ );
++ const pendingTxs = sameFromAndNetworkTransactions.filter(
++ (transaction) => transaction.status === "submitted" /* submitted */
++ );
++ validateConfirmedExternalTransaction(
++ transactionMeta,
++ confirmedTxs,
++ pendingTxs
++ );
++ const newTransactionMeta = (transactionMeta.history ?? []).length === 0 && !this.isHistoryDisabled ? addInitialHistorySnapshot(transactionMeta) : transactionMeta;
++ this.update((state) => {
++ state.transactions = this.trimTransactionsForState([
++ ...state.transactions,
++ newTransactionMeta
++ ]);
++ });
++ return newTransactionMeta;
++ }
++ /**
++ * Sets other txMeta statuses to dropped if the txMeta that has been confirmed has other transactions
++ * in the transactions have the same nonce.
++ *
++ * @param transactionId - Used to identify original transaction.
++ */
++ markNonceDuplicatesDropped(transactionId) {
++ const transactionMeta = this.getTransaction(transactionId);
++ if (!transactionMeta) {
++ return;
++ }
++ const nonce = transactionMeta.txParams?.nonce;
++ const from = transactionMeta.txParams?.from;
++ const { chainId } = transactionMeta;
++ const sameNonceTransactions = this.state.transactions.filter(
++ (transaction) => transaction.id !== transactionId && transaction.txParams.from === from && transaction.txParams.nonce === nonce && transaction.chainId === chainId && transaction.type !== "incoming" /* incoming */
++ );
++ const sameNonceTransactionIds = sameNonceTransactions.map(
++ (transaction) => transaction.id
++ );
++ if (sameNonceTransactions.length === 0) {
++ return;
++ }
++ this.update((state) => {
++ for (const transaction of state.transactions) {
++ if (sameNonceTransactionIds.includes(transaction.id)) {
++ transaction.replacedBy = transactionMeta?.hash;
++ transaction.replacedById = transactionMeta?.id;
++ }
++ }
++ });
++ for (const transaction of this.state.transactions) {
++ if (sameNonceTransactionIds.includes(transaction.id) && transaction.status !== "failed" /* failed */) {
++ this.setTransactionStatusDropped(transaction);
++ }
++ }
++ }
++ /**
++ * Method to set transaction status to dropped.
++ *
++ * @param transactionMeta - TransactionMeta of transaction to be marked as dropped.
++ */
++ setTransactionStatusDropped(transactionMeta) {
++ const updatedTransactionMeta = {
++ ...transactionMeta,
++ status: "dropped" /* dropped */
++ };
++ this.messagingSystem.publish(`${controllerName}:transactionDropped`, {
++ transactionMeta: updatedTransactionMeta
++ });
++ this.updateTransaction(
++ updatedTransactionMeta,
++ "TransactionController#setTransactionStatusDropped - Transaction dropped"
++ );
++ this.onTransactionStatusChange(updatedTransactionMeta);
++ }
++ /**
++ * Get transaction with provided actionId.
++ *
++ * @param actionId - Unique ID to prevent duplicate requests
++ * @returns the filtered transaction
++ */
++ getTransactionWithActionId(actionId) {
++ return this.state.transactions.find(
++ (transaction) => actionId && transaction.actionId === actionId
++ );
++ }
++ async waitForTransactionFinished(transactionId) {
++ return new Promise((resolve) => {
++ __privateGet(this, _internalEvents).once(`${transactionId}:finished`, (txMeta) => {
++ resolve(txMeta);
++ });
++ });
++ }
++ /**
++ * Updates the r, s, and v properties of a TransactionMeta object
++ * with values from a signed transaction.
++ *
++ * @param transactionMeta - The TransactionMeta object to update.
++ * @param signedTx - The encompassing type for all transaction types containing r, s, and v values.
++ * @returns The updated TransactionMeta object.
++ */
++ updateTransactionMetaRSV(transactionMeta, signedTx) {
++ const transactionMetaWithRsv = cloneDeep(transactionMeta);
++ for (const key of ["r", "s", "v"]) {
++ const value = signedTx[key];
++ if (value === void 0 || value === null) {
++ continue;
++ }
++ transactionMetaWithRsv[key] = add0x(value.toString(16));
++ }
++ return transactionMetaWithRsv;
++ }
++ async getEIP1559Compatibility(networkClientId) {
++ const currentNetworkIsEIP1559Compatible = await this.getCurrentNetworkEIP1559Compatibility(networkClientId);
++ const currentAccountIsEIP1559Compatible = await this.getCurrentAccountEIP1559Compatibility();
++ return currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible;
++ }
++ async signTransaction(transactionMeta, txParams) {
++ projectLogger("Signing transaction", txParams);
++ const unsignedEthTx = this.prepareUnsignedEthTx(
++ transactionMeta.chainId,
++ txParams
++ );
++ this.approvingTransactionIds.add(transactionMeta.id);
++ const signedTx = await new Promise((resolve, reject) => {
++ this.sign?.(
++ unsignedEthTx,
++ txParams.from,
++ ...this.getAdditionalSignArguments(transactionMeta)
++ ).then(resolve, reject);
++ this.signAbortCallbacks.set(
++ transactionMeta.id,
++ () => reject(new Error("Signing aborted by user"))
++ );
++ });
++ this.signAbortCallbacks.delete(transactionMeta.id);
++ if (!signedTx) {
++ projectLogger("Skipping signed status as no signed transaction");
++ return void 0;
++ }
++ const transactionMetaFromHook = cloneDeep(transactionMeta);
++ if (!this.afterSign(transactionMetaFromHook, signedTx)) {
++ this.updateTransaction(
++ transactionMetaFromHook,
++ "TransactionController#signTransaction - Update after sign"
++ );
++ projectLogger("Skipping signed status based on hook");
++ return void 0;
++ }
++ const transactionMetaWithRsv = {
++ ...this.updateTransactionMetaRSV(transactionMetaFromHook, signedTx),
++ status: "signed" /* signed */
++ };
++ this.updateTransaction(
++ transactionMetaWithRsv,
++ "TransactionController#approveTransaction - Transaction signed"
++ );
++ this.onTransactionStatusChange(transactionMetaWithRsv);
++ const rawTx = bufferToHex(signedTx.serialize());
++ const transactionMetaWithRawTx = merge({}, transactionMetaWithRsv, {
++ rawTx
++ });
++ this.updateTransaction(
++ transactionMetaWithRawTx,
++ "TransactionController#approveTransaction - RawTransaction added"
++ );
++ return rawTx;
++ }
++ onTransactionStatusChange(transactionMeta) {
++ this.messagingSystem.publish(`${controllerName}:transactionStatusUpdated`, {
++ transactionMeta
++ });
++ }
++ getNonceTrackerTransactions(status, address, chainId = this.getChainId()) {
++ return getAndFormatTransactionsForNonceTracker(
++ chainId,
++ address,
++ status,
++ this.state.transactions
++ );
++ }
++ onConfirmedTransaction(transactionMeta) {
++ projectLogger("Processing confirmed transaction", transactionMeta.id);
++ this.markNonceDuplicatesDropped(transactionMeta.id);
++ this.messagingSystem.publish(
++ `${controllerName}:transactionConfirmed`,
++ transactionMeta
++ );
++ this.onTransactionStatusChange(transactionMeta);
++ this.updatePostBalance(transactionMeta);
++ }
++ async updatePostBalance(transactionMeta) {
++ try {
++ if (transactionMeta.type !== "swap" /* swap */) {
++ return;
++ }
++ const ethQuery = __privateGet(this, _multichainTrackingHelper).getEthQuery({
++ networkClientId: transactionMeta.networkClientId,
++ chainId: transactionMeta.chainId
++ });
++ const { updatedTransactionMeta, approvalTransactionMeta } = await updatePostTransactionBalance(transactionMeta, {
++ ethQuery,
++ getTransaction: this.getTransaction.bind(this),
++ updateTransaction: this.updateTransaction.bind(this)
++ });
++ this.messagingSystem.publish(
++ `${controllerName}:postTransactionBalanceUpdated`,
++ {
++ transactionMeta: updatedTransactionMeta,
++ approvalTransactionMeta
++ }
++ );
++ } catch (error) {
++ projectLogger("Error while updating post transaction balance", error);
++ }
++ }
++ async publishTransactionForRetry(ethQuery, rawTx, transactionMeta) {
++ try {
++ const hash = await this.publishTransaction(ethQuery, rawTx);
++ return hash;
++ } catch (error) {
++ if (this.isTransactionAlreadyConfirmedError(error)) {
++ await this.pendingTransactionTracker.forceCheckTransaction(
++ transactionMeta
++ );
++ throw new Error("Previous transaction is already confirmed");
++ }
++ throw error;
++ }
++ }
++ /**
++ * Ensures that error is a nonce issue
++ *
++ * @param error - The error to check
++ * @returns Whether or not the error is a nonce issue
++ */
++ // TODO: Replace `any` with type
++ // Some networks are returning original error in the data field
++ // eslint-disable-next-line @typescript-eslint/no-explicit-any
++ isTransactionAlreadyConfirmedError(error) {
++ return error?.message?.includes("nonce too low") || error?.data?.message?.includes("nonce too low");
++ }
++};
++_internalEvents = new WeakMap();
++_incomingTransactionOptions = new WeakMap();
++_pendingTransactionOptions = new WeakMap();
++_transactionHistoryLimit = new WeakMap();
++_isSimulationEnabled = new WeakMap();
++_testGasFeeFlows = new WeakMap();
++_multichainTrackingHelper = new WeakMap();
++_createNonceTracker = new WeakSet();
++createNonceTracker_fn = function({
++ provider,
++ blockTracker,
++ chainId
++}) {
++ return new NonceTracker({
++ // TODO: Fix types
++ // eslint-disable-next-line @typescript-eslint/no-explicit-any
++ provider,
++ // @ts-expect-error TODO: Fix types
++ blockTracker,
++ getPendingTransactions: __privateMethod(this, _getNonceTrackerPendingTransactions, getNonceTrackerPendingTransactions_fn).bind(
++ this,
++ chainId
++ ),
++ getConfirmedTransactions: this.getNonceTrackerTransactions.bind(
++ this,
++ "confirmed" /* confirmed */
++ )
++ });
++};
++_createIncomingTransactionHelper = new WeakSet();
++createIncomingTransactionHelper_fn = function({
++ blockTracker,
++ etherscanRemoteTransactionSource,
++ chainId
++}) {
++ const incomingTransactionHelper = new IncomingTransactionHelper({
++ blockTracker,
++ getCurrentAccount: () => __privateMethod(this, _getSelectedAccount, getSelectedAccount_fn).call(this),
++ getLastFetchedBlockNumbers: () => this.state.lastFetchedBlockNumbers,
++ getChainId: chainId ? () => chainId : this.getChainId.bind(this),
++ isEnabled: __privateGet(this, _incomingTransactionOptions).isEnabled,
++ queryEntireHistory: __privateGet(this, _incomingTransactionOptions).queryEntireHistory,
++ remoteTransactionSource: etherscanRemoteTransactionSource,
++ transactionLimit: __privateGet(this, _transactionHistoryLimit),
++ updateTransactions: __privateGet(this, _incomingTransactionOptions).updateTransactions
++ });
++ __privateMethod(this, _addIncomingTransactionHelperListeners, addIncomingTransactionHelperListeners_fn).call(this, incomingTransactionHelper);
++ return incomingTransactionHelper;
++};
++_createPendingTransactionTracker = new WeakSet();
++createPendingTransactionTracker_fn = function({
++ provider,
++ blockTracker,
++ chainId
++}) {
++ const ethQuery = new EthQuery(provider);
++ const getChainId = chainId ? () => chainId : this.getChainId.bind(this);
++ const pendingTransactionTracker = new PendingTransactionTracker({
++ blockTracker,
++ getChainId,
++ getEthQuery: () => ethQuery,
++ getTransactions: () => this.state.transactions,
++ isResubmitEnabled: __privateGet(this, _pendingTransactionOptions).isResubmitEnabled,
++ getGlobalLock: () => __privateGet(this, _multichainTrackingHelper).acquireNonceLockForChainIdKey({
++ chainId: getChainId()
++ }),
++ publishTransaction: this.publishTransaction.bind(this),
++ hooks: {
++ beforeCheckPendingTransaction: this.beforeCheckPendingTransaction.bind(this),
++ beforePublish: this.beforePublish.bind(this)
++ }
++ });
++ __privateMethod(this, _addPendingTransactionTrackerListeners, addPendingTransactionTrackerListeners_fn).call(this, pendingTransactionTracker);
++ return pendingTransactionTracker;
++};
++_checkForPendingTransactionAndStartPolling = new WeakMap();
++_stopAllTracking = new WeakSet();
++stopAllTracking_fn = function() {
++ this.pendingTransactionTracker.stop();
++ __privateMethod(this, _removePendingTransactionTrackerListeners, removePendingTransactionTrackerListeners_fn).call(this, this.pendingTransactionTracker);
++ this.incomingTransactionHelper.stop();
++ __privateMethod(this, _removeIncomingTransactionHelperListeners, removeIncomingTransactionHelperListeners_fn).call(this, this.incomingTransactionHelper);
++ __privateGet(this, _multichainTrackingHelper).stopAllTracking();
++};
++_removeIncomingTransactionHelperListeners = new WeakSet();
++removeIncomingTransactionHelperListeners_fn = function(incomingTransactionHelper) {
++ incomingTransactionHelper.hub.removeAllListeners("transactions");
++ incomingTransactionHelper.hub.removeAllListeners(
++ "updatedLastFetchedBlockNumbers"
++ );
++};
++_addIncomingTransactionHelperListeners = new WeakSet();
++addIncomingTransactionHelperListeners_fn = function(incomingTransactionHelper) {
++ incomingTransactionHelper.hub.on(
++ "transactions",
++ this.onIncomingTransactions.bind(this)
++ );
++ incomingTransactionHelper.hub.on(
++ "updatedLastFetchedBlockNumbers",
++ this.onUpdatedLastFetchedBlockNumbers.bind(this)
++ );
++};
++_removePendingTransactionTrackerListeners = new WeakSet();
++removePendingTransactionTrackerListeners_fn = function(pendingTransactionTracker) {
++ pendingTransactionTracker.hub.removeAllListeners("transaction-confirmed");
++ pendingTransactionTracker.hub.removeAllListeners("transaction-dropped");
++ pendingTransactionTracker.hub.removeAllListeners("transaction-failed");
++ pendingTransactionTracker.hub.removeAllListeners("transaction-updated");
++};
++_addPendingTransactionTrackerListeners = new WeakSet();
++addPendingTransactionTrackerListeners_fn = function(pendingTransactionTracker) {
++ pendingTransactionTracker.hub.on(
++ "transaction-confirmed",
++ this.onConfirmedTransaction.bind(this)
++ );
++ pendingTransactionTracker.hub.on(
++ "transaction-dropped",
++ this.setTransactionStatusDropped.bind(this)
++ );
++ pendingTransactionTracker.hub.on(
++ "transaction-failed",
++ this.failTransaction.bind(this)
++ );
++ pendingTransactionTracker.hub.on(
++ "transaction-updated",
++ this.updateTransaction.bind(this)
++ );
++};
++_getNonceTrackerPendingTransactions = new WeakSet();
++getNonceTrackerPendingTransactions_fn = function(chainId, address) {
++ const standardPendingTransactions = this.getNonceTrackerTransactions(
++ "submitted" /* submitted */,
++ address,
++ chainId
++ );
++ const externalPendingTransactions = this.getExternalPendingTransactions(
++ address,
++ chainId
++ );
++ return [...standardPendingTransactions, ...externalPendingTransactions];
++};
++_getGasFeeFlows = new WeakSet();
++getGasFeeFlows_fn = function() {
++ if (__privateGet(this, _testGasFeeFlows)) {
++ return [new TestGasFeeFlow()];
++ }
++ return [new LineaGasFeeFlow(), new DefaultGasFeeFlow()];
++};
++_getLayer1GasFeeFlows = new WeakSet();
++getLayer1GasFeeFlows_fn = function() {
++ return [new OptimismLayer1GasFeeFlow(), new ScrollLayer1GasFeeFlow()];
++};
++_updateTransactionInternal = new WeakSet();
++updateTransactionInternal_fn = function({
++ transactionId,
++ note,
++ skipHistory,
++ skipValidation
++}, callback) {
++ let updatedTransactionParams = [];
++ this.update((state) => {
++ const index = state.transactions.findIndex(
++ ({ id }) => id === transactionId
++ );
++ let transactionMeta2 = state.transactions[index];
++ transactionMeta2 = callback(transactionMeta2) ?? transactionMeta2;
++ if (skipValidation !== true) {
++ transactionMeta2.txParams = normalizeTransactionParams(
++ transactionMeta2.txParams
++ );
++ validateTxParams(transactionMeta2.txParams);
++ }
++ updatedTransactionParams = __privateMethod(this, _checkIfTransactionParamsUpdated, checkIfTransactionParamsUpdated_fn).call(this, transactionMeta2);
++ const shouldSkipHistory = this.isHistoryDisabled || skipHistory;
++ if (!shouldSkipHistory) {
++ transactionMeta2 = updateTransactionHistory(
++ transactionMeta2,
++ note ?? "Transaction updated"
++ );
++ }
++ state.transactions[index] = transactionMeta2;
++ });
++ const transactionMeta = this.getTransaction(
++ transactionId
++ );
++ if (updatedTransactionParams.length > 0) {
++ __privateMethod(this, _onTransactionParamsUpdated, onTransactionParamsUpdated_fn).call(this, transactionMeta, updatedTransactionParams);
++ }
++ return transactionMeta;
++};
++_checkIfTransactionParamsUpdated = new WeakSet();
++checkIfTransactionParamsUpdated_fn = function(newTransactionMeta) {
++ const { id: transactionId, txParams: newParams } = newTransactionMeta;
++ const originalParams = this.getTransaction(transactionId)?.txParams;
++ if (!originalParams || isEqual(originalParams, newParams)) {
++ return [];
++ }
++ const params = Object.keys(newParams);
++ const updatedProperties = params.filter(
++ (param) => newParams[param] !== originalParams[param]
++ );
++ projectLogger(
++ "Transaction parameters have been updated",
++ transactionId,
++ updatedProperties,
++ originalParams,
++ newParams
++ );
++ return updatedProperties;
++};
++_onTransactionParamsUpdated = new WeakSet();
++onTransactionParamsUpdated_fn = function(transactionMeta, updatedParams) {
++ if (["to", "value", "data"].some(
++ (param) => updatedParams.includes(param)
++ )) {
++ projectLogger("Updating simulation data due to transaction parameter update");
++ __privateMethod(this, _updateSimulationData, updateSimulationData_fn).call(this, transactionMeta);
++ }
++};
++_updateSimulationData = new WeakSet();
++updateSimulationData_fn = async function(transactionMeta) {
++ const { id: transactionId, chainId, txParams } = transactionMeta;
++ const { from, to, value, data } = txParams;
++ let simulationData = {
++ error: {
++ code: "disabled" /* Disabled */,
++ message: "Simulation disabled"
++ },
++ tokenBalanceChanges: []
++ };
++ if (__privateGet(this, _isSimulationEnabled).call(this)) {
++ __privateMethod(this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, { transactionId, skipHistory: true }, (txMeta) => {
++ txMeta.simulationData = void 0;
++ });
++ simulationData = await getSimulationData({
++ chainId,
++ from,
++ to,
++ value,
++ data
++ });
++ }
++ const finalTransactionMeta = this.getTransaction(transactionId);
++ if (!finalTransactionMeta) {
++ projectLogger(
++ "Cannot update simulation data as transaction not found",
++ transactionId,
++ simulationData
++ );
++ return;
++ }
++ __privateMethod(this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, {
++ transactionId,
++ note: "TransactionController#updateSimulationData - Update simulation data"
++ }, (txMeta) => {
++ txMeta.simulationData = simulationData;
++ });
++ projectLogger("Updated simulation data", transactionId, simulationData);
++};
++_onGasFeePollerTransactionUpdate = new WeakSet();
++onGasFeePollerTransactionUpdate_fn = function({
++ transactionId,
++ gasFeeEstimates,
++ gasFeeEstimatesLoaded,
++ layer1GasFee
++}) {
++ __privateMethod(this, _updateTransactionInternal, updateTransactionInternal_fn).call(this, { transactionId, skipHistory: true }, (txMeta) => {
++ if (gasFeeEstimates) {
++ txMeta.gasFeeEstimates = gasFeeEstimates;
++ }
++ if (gasFeeEstimatesLoaded !== void 0) {
++ txMeta.gasFeeEstimatesLoaded = gasFeeEstimatesLoaded;
++ }
++ if (layer1GasFee) {
++ txMeta.layer1GasFee = layer1GasFee;
++ }
++ });
++};
++_getNetworkClientId = new WeakSet();
++getNetworkClientId_fn = function({
++ networkClientId: requestNetworkClientId,
++ chainId
++}) {
++ const globalChainId = __privateMethod(this, _getGlobalChainId, getGlobalChainId_fn).call(this);
++ const globalNetworkClientId = __privateMethod(this, _getGlobalNetworkClientId, getGlobalNetworkClientId_fn).call(this);
++ if (requestNetworkClientId) {
++ return requestNetworkClientId;
++ }
++ if (!chainId || chainId === globalChainId) {
++ return globalNetworkClientId;
++ }
++ return this.messagingSystem.call(
++ `NetworkController:findNetworkClientIdByChainId`,
++ chainId
++ );
++};
++_getGlobalNetworkClientId = new WeakSet();
++getGlobalNetworkClientId_fn = function() {
++ return this.getNetworkState().selectedNetworkClientId;
++};
++_getGlobalChainId = new WeakSet();
++getGlobalChainId_fn = function() {
++ return this.messagingSystem.call(
++ `NetworkController:getNetworkClientById`,
++ this.getNetworkState().selectedNetworkClientId
++ ).configuration.chainId;
++};
++_isCustomNetwork = new WeakSet();
++isCustomNetwork_fn = function(networkClientId) {
++ const globalNetworkClientId = __privateMethod(this, _getGlobalNetworkClientId, getGlobalNetworkClientId_fn).call(this);
++ if (!networkClientId || networkClientId === globalNetworkClientId) {
++ return !isInfuraNetworkType(
++ this.getNetworkState().selectedNetworkClientId
++ );
++ }
++ return this.messagingSystem.call(
++ `NetworkController:getNetworkClientById`,
++ networkClientId
++ ).configuration.type === NetworkClientType.Custom;
++};
++_getSelectedAccount = new WeakSet();
++getSelectedAccount_fn = function() {
++ return this.messagingSystem.call("AccountsController:getSelectedAccount");
++};
++
++export {
++ HARDFORK,
++ CANCEL_RATE,
++ SPEED_UP_RATE,
++ ApprovalState,
++ TransactionController
++};
++//# sourceMappingURL=chunk-YQYO6EGF.mjs.map
+\ No newline at end of file
+diff --git a/dist/chunk-YQYO6EGF.mjs.map b/dist/chunk-YQYO6EGF.mjs.map
+new file mode 100644
+index 0000000000000000000000000000000000000000..d0f3b3d31c6e0ad96b3d873dd82bdbdc0cdf7abe
+--- /dev/null
++++ b/dist/chunk-YQYO6EGF.mjs.map
+@@ -0,0 +1 @@
++{"version":3,"sources":["../src/TransactionController.ts"],"sourcesContent":["import { Hardfork, Common, type ChainConfig } from '@ethereumjs/common';\nimport type { TypedTransaction } from '@ethereumjs/tx';\nimport { TransactionFactory } from '@ethereumjs/tx';\nimport { bufferToHex } from '@ethereumjs/util';\nimport type { AccountsControllerGetSelectedAccountAction } from '@metamask/accounts-controller';\nimport type {\n AcceptResultCallbacks,\n AddApprovalRequest,\n AddResult,\n} from '@metamask/approval-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport {\n query,\n ApprovalType,\n ORIGIN_METAMASK,\n convertHexToDecimal,\n isInfuraNetworkType,\n} from '@metamask/controller-utils';\nimport EthQuery from '@metamask/eth-query';\nimport type {\n FetchGasFeeEstimateOptions,\n GasFeeState,\n} from '@metamask/gas-fee-controller';\nimport type {\n BlockTracker,\n NetworkClientId,\n NetworkController,\n NetworkControllerStateChangeEvent,\n NetworkState,\n Provider,\n NetworkControllerFindNetworkClientIdByChainIdAction,\n NetworkControllerGetNetworkClientByIdAction,\n} from '@metamask/network-controller';\nimport { NetworkClientType } from '@metamask/network-controller';\nimport type {\n NonceLock,\n Transaction as NonceTrackerTransaction,\n} from '@metamask/nonce-tracker';\nimport { NonceTracker } from '@metamask/nonce-tracker';\nimport { errorCodes, rpcErrors, providerErrors } from '@metamask/rpc-errors';\nimport type { Hex } from '@metamask/utils';\nimport { add0x } from '@metamask/utils';\nimport { Mutex } from 'async-mutex';\nimport { MethodRegistry } from 'eth-method-registry';\nimport { EventEmitter } from 'events';\nimport { cloneDeep, mapValues, merge, pickBy, sortBy, isEqual } from 'lodash';\nimport { v1 as random } from 'uuid';\n\nimport { DefaultGasFeeFlow } from './gas-flows/DefaultGasFeeFlow';\nimport { LineaGasFeeFlow } from './gas-flows/LineaGasFeeFlow';\nimport { OptimismLayer1GasFeeFlow } from './gas-flows/OptimismLayer1GasFeeFlow';\nimport { ScrollLayer1GasFeeFlow } from './gas-flows/ScrollLayer1GasFeeFlow';\nimport { TestGasFeeFlow } from './gas-flows/TestGasFeeFlow';\nimport { EtherscanRemoteTransactionSource } from './helpers/EtherscanRemoteTransactionSource';\nimport { GasFeePoller } from './helpers/GasFeePoller';\nimport type { IncomingTransactionOptions } from './helpers/IncomingTransactionHelper';\nimport { IncomingTransactionHelper } from './helpers/IncomingTransactionHelper';\nimport { MultichainTrackingHelper } from './helpers/MultichainTrackingHelper';\nimport { PendingTransactionTracker } from './helpers/PendingTransactionTracker';\nimport { projectLogger as log } from './logger';\nimport type {\n DappSuggestedGasFees,\n Layer1GasFeeFlow,\n SavedGasFees,\n SecurityProviderRequest,\n SendFlowHistoryEntry,\n TransactionParams,\n TransactionMeta,\n TransactionReceipt,\n WalletDevice,\n SecurityAlertResponse,\n GasFeeFlow,\n SimulationData,\n GasFeeEstimates,\n GasFeeFlowResponse,\n} from './types';\nimport {\n TransactionEnvelopeType,\n TransactionType,\n TransactionStatus,\n SimulationErrorCode,\n} from './types';\nimport { validateConfirmedExternalTransaction } from './utils/external-transactions';\nimport { addGasBuffer, estimateGas, updateGas } from './utils/gas';\nimport { updateGasFees } from './utils/gas-fees';\nimport { getGasFeeFlow } from './utils/gas-flow';\nimport {\n addInitialHistorySnapshot,\n updateTransactionHistory,\n} from './utils/history';\nimport {\n getTransactionLayer1GasFee,\n updateTransactionLayer1GasFee,\n} from './utils/layer1-gas-fee-flow';\nimport {\n getAndFormatTransactionsForNonceTracker,\n getNextNonce,\n} from './utils/nonce';\nimport { getSimulationData } from './utils/simulation';\nimport {\n updatePostTransactionBalance,\n updateSwapsTransaction,\n} from './utils/swaps';\nimport { determineTransactionType } from './utils/transaction-type';\nimport {\n getIncreasedPriceFromExisting,\n normalizeTransactionParams,\n isEIP1559Transaction,\n isFeeMarketEIP1559Values,\n isGasPriceValue,\n validateGasValues,\n validateIfTransactionUnapproved,\n validateMinimumIncrease,\n normalizeTxError,\n normalizeGasFeeValues,\n} from './utils/utils';\nimport {\n validateTransactionOrigin,\n validateTxParams,\n} from './utils/validation';\n\n/**\n * Metadata for the TransactionController state, describing how to \"anonymize\"\n * the state and which parts should be persisted.\n */\nconst metadata = {\n transactions: {\n persist: true,\n anonymous: false,\n },\n methodData: {\n persist: true,\n anonymous: false,\n },\n lastFetchedBlockNumbers: {\n persist: true,\n anonymous: false,\n },\n};\n\nexport const HARDFORK = Hardfork.London;\n\n/**\n * Object with new transaction's meta and a promise resolving to the\n * transaction hash if successful.\n *\n * @property result - Promise resolving to a new transaction hash\n * @property transactionMeta - Meta information about this new transaction\n */\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface Result {\n result: Promise;\n transactionMeta: TransactionMeta;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface GasPriceValue {\n gasPrice: string;\n}\n\n// This interface was created before this ESLint rule was added.\n// Convert to a `type` in a future major version.\n// eslint-disable-next-line @typescript-eslint/consistent-type-definitions\nexport interface FeeMarketEIP1559Values {\n maxFeePerGas: string;\n maxPriorityFeePerGas: string;\n}\n\n/**\n * Method data registry object\n *\n * @property registryMethod - Registry method raw string\n * @property parsedRegistryMethod - Registry method object, containing name and method arguments\n */\nexport type MethodData = {\n registryMethod: string;\n parsedRegistryMethod:\n | {\n name: string;\n args: { type: string }[];\n }\n | {\n // We're using `any` instead of `undefined` for compatibility with `Json`\n // TODO: Correct this type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n name?: any;\n // We're using `any` instead of `undefined` for compatibility with `Json`\n // TODO: Correct this type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n args?: any;\n };\n};\n\n/**\n * Transaction controller state\n *\n * @property transactions - A list of TransactionMeta objects\n * @property methodData - Object containing all known method data information\n * @property lastFetchedBlockNumbers - Last fetched block numbers.\n */\nexport type TransactionControllerState = {\n transactions: TransactionMeta[];\n methodData: Record;\n lastFetchedBlockNumbers: { [key: string]: number };\n};\n\n/**\n * Multiplier used to determine a transaction's increased gas fee during cancellation\n */\nexport const CANCEL_RATE = 1.1;\n\n/**\n * Multiplier used to determine a transaction's increased gas fee during speed up\n */\nexport const SPEED_UP_RATE = 1.1;\n\n/**\n * Represents the `TransactionController:getState` action.\n */\nexport type TransactionControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n TransactionControllerState\n>;\n\n/**\n * The internal actions available to the TransactionController.\n */\nexport type TransactionControllerActions = TransactionControllerGetStateAction;\n\n/**\n * Configuration options for the PendingTransactionTracker\n *\n * @property isResubmitEnabled - Whether transaction publishing is automatically retried.\n */\nexport type PendingTransactionOptions = {\n isResubmitEnabled?: () => boolean;\n};\n\n/**\n * TransactionController constructor options.\n *\n * @property blockTracker - The block tracker used to poll for new blocks data.\n * @property disableHistory - Whether to disable storing history in transaction metadata.\n * @property disableSendFlowHistory - Explicitly disable transaction metadata history.\n * @property disableSwaps - Whether to disable additional processing on swaps transactions.\n * @property getCurrentAccountEIP1559Compatibility - Whether or not the account supports EIP-1559.\n * @property getCurrentNetworkEIP1559Compatibility - Whether or not the network supports EIP-1559.\n * @property getExternalPendingTransactions - Callback to retrieve pending transactions from external sources.\n * @property getGasFeeEstimates - Callback to retrieve gas fee estimates.\n * @property getNetworkClientRegistry - Gets the network client registry.\n * @property getNetworkState - Gets the state of the network controller.\n * @property getPermittedAccounts - Get accounts that a given origin has permissions for.\n * @property getSavedGasFees - Gets the saved gas fee config.\n * @property getSelectedAddress - Gets the address of the currently selected account.\n * @property incomingTransactions - Configuration options for incoming transaction support.\n * @property isMultichainEnabled - Enable multichain support.\n * @property isSimulationEnabled - Whether new transactions will be automatically simulated.\n * @property messenger - The controller messenger.\n * @property onNetworkStateChange - Allows subscribing to network controller state changes.\n * @property pendingTransactions - Configuration options for pending transaction support.\n * @property provider - The provider used to create the underlying EthQuery instance.\n * @property securityProviderRequest - A function for verifying a transaction, whether it is malicious or not.\n * @property sign - Function used to sign transactions.\n * @property state - Initial state to set on this controller.\n * @property transactionHistoryLimit - Transaction history limit.\n * @property hooks - The controller hooks.\n * @property hooks.afterSign - Additional logic to execute after signing a transaction. Return false to not change the status to signed.\n * @property hooks.beforeCheckPendingTransaction - Additional logic to execute before checking pending transactions. Return false to prevent the broadcast of the transaction.\n * @property hooks.beforePublish - Additional logic to execute before publishing a transaction. Return false to prevent the broadcast of the transaction.\n * @property hooks.getAdditionalSignArguments - Returns additional arguments required to sign a transaction.\n * @property hooks.publish - Alternate logic to publish a transaction.\n */\nexport type TransactionControllerOptions = {\n blockTracker: BlockTracker;\n disableHistory: boolean;\n disableSendFlowHistory: boolean;\n disableSwaps: boolean;\n getCurrentAccountEIP1559Compatibility?: () => Promise;\n getCurrentNetworkEIP1559Compatibility: () => Promise;\n getExternalPendingTransactions?: (\n address: string,\n chainId?: string,\n ) => NonceTrackerTransaction[];\n getGasFeeEstimates?: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise;\n getNetworkClientRegistry: NetworkController['getNetworkClientRegistry'];\n getNetworkState: () => NetworkState;\n getPermittedAccounts: (origin?: string) => Promise;\n getSavedGasFees?: (chainId: Hex) => SavedGasFees | undefined;\n incomingTransactions?: IncomingTransactionOptions;\n isMultichainEnabled: boolean;\n isSimulationEnabled?: () => boolean;\n messenger: TransactionControllerMessenger;\n onNetworkStateChange: (listener: (state: NetworkState) => void) => void;\n pendingTransactions?: PendingTransactionOptions;\n provider: Provider;\n securityProviderRequest?: SecurityProviderRequest;\n sign?: (\n transaction: TypedTransaction,\n from: string,\n transactionMeta?: TransactionMeta,\n ) => Promise;\n state?: Partial;\n testGasFeeFlows?: boolean;\n transactionHistoryLimit: number;\n hooks: {\n afterSign?: (\n transactionMeta: TransactionMeta,\n signedTx: TypedTransaction,\n ) => boolean;\n beforeCheckPendingTransaction?: (\n transactionMeta: TransactionMeta,\n ) => boolean;\n beforePublish?: (transactionMeta: TransactionMeta) => boolean;\n getAdditionalSignArguments?: (\n transactionMeta: TransactionMeta,\n ) => (TransactionMeta | undefined)[];\n publish?: (\n transactionMeta: TransactionMeta,\n ) => Promise<{ transactionHash: string }>;\n };\n};\n\n/**\n * The name of the {@link TransactionController}.\n */\nconst controllerName = 'TransactionController';\n\n/**\n * The external actions available to the {@link TransactionController}.\n */\nexport type AllowedActions =\n | AddApprovalRequest\n | NetworkControllerFindNetworkClientIdByChainIdAction\n | NetworkControllerGetNetworkClientByIdAction\n | AccountsControllerGetSelectedAccountAction;\n\n/**\n * The external events available to the {@link TransactionController}.\n */\nexport type AllowedEvents = NetworkControllerStateChangeEvent;\n\n/**\n * Represents the `TransactionController:stateChange` event.\n */\nexport type TransactionControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n TransactionControllerState\n>;\n\n/**\n * Represents the `TransactionController:incomingTransactionBlockReceived` event.\n */\nexport type TransactionControllerIncomingTransactionBlockReceivedEvent = {\n type: `${typeof controllerName}:incomingTransactionBlockReceived`;\n payload: [blockNumber: number];\n};\n\n/**\n * Represents the `TransactionController:postTransactionBalanceUpdated` event.\n */\nexport type TransactionControllerPostTransactionBalanceUpdatedEvent = {\n type: `${typeof controllerName}:postTransactionBalanceUpdated`;\n payload: [\n {\n transactionMeta: TransactionMeta;\n approvalTransactionMeta?: TransactionMeta;\n },\n ];\n};\n\n/**\n * Represents the `TransactionController:speedUpTransactionAdded` event.\n */\nexport type TransactionControllerSpeedupTransactionAddedEvent = {\n type: `${typeof controllerName}:speedupTransactionAdded`;\n payload: [transactionMeta: TransactionMeta];\n};\n\n/**\n * Represents the `TransactionController:transactionApproved` event.\n */\nexport type TransactionControllerTransactionApprovedEvent = {\n type: `${typeof controllerName}:transactionApproved`;\n payload: [\n {\n transactionMeta: TransactionMeta;\n actionId?: string;\n },\n ];\n};\n\n/**\n * Represents the `TransactionController:transactionConfirmed` event.\n */\nexport type TransactionControllerTransactionConfirmedEvent = {\n type: `${typeof controllerName}:transactionConfirmed`;\n payload: [transactionMeta: TransactionMeta];\n};\n\n/**\n * Represents the `TransactionController:transactionDropped` event.\n */\nexport type TransactionControllerTransactionDroppedEvent = {\n type: `${typeof controllerName}:transactionDropped`;\n payload: [{ transactionMeta: TransactionMeta }];\n};\n\n/**\n * Represents the `TransactionController:transactionFailed` event.\n */\nexport type TransactionControllerTransactionFailedEvent = {\n type: `${typeof controllerName}:transactionFailed`;\n payload: [\n {\n actionId?: string;\n error: string;\n transactionMeta: TransactionMeta;\n },\n ];\n};\n\n/**\n * Represents the `TransactionController:transactionFinished` event.\n */\nexport type TransactionControllerTransactionFinishedEvent = {\n type: `${typeof controllerName}:transactionFinished`;\n payload: [transactionMeta: TransactionMeta];\n};\n\n/**\n * Represents the `TransactionController:transactionNewSwapApproval` event.\n */\nexport type TransactionControllerTransactionNewSwapApprovalEvent = {\n type: `${typeof controllerName}:transactionNewSwapApproval`;\n payload: [{ transactionMeta: TransactionMeta }];\n};\n\n/**\n * Represents the `TransactionController:transactionNewSwap` event.\n */\nexport type TransactionControllerTransactionNewSwapEvent = {\n type: `${typeof controllerName}:transactionNewSwap`;\n payload: [{ transactionMeta: TransactionMeta }];\n};\n\n/**\n * Represents the `TransactionController:transactionNewSwapApproval` event.\n */\nexport type TransactionControllerTransactionNewSwapAndSendEvent = {\n type: `${typeof controllerName}:transactionNewSwapAndSend`;\n payload: [{ transactionMeta: TransactionMeta }];\n};\n\n/**\n * Represents the `TransactionController:transactionPublishingSkipped` event.\n */\nexport type TransactionControllerTransactionPublishingSkipped = {\n type: `${typeof controllerName}:transactionPublishingSkipped`;\n payload: [transactionMeta: TransactionMeta];\n};\n\n/**\n * Represents the `TransactionController:transactionRejected` event.\n */\nexport type TransactionControllerTransactionRejectedEvent = {\n type: `${typeof controllerName}:transactionRejected`;\n payload: [\n {\n transactionMeta: TransactionMeta;\n actionId?: string;\n },\n ];\n};\n\n/**\n * Represents the `TransactionController:transactionStatusUpdated` event.\n */\nexport type TransactionControllerTransactionStatusUpdatedEvent = {\n type: `${typeof controllerName}:transactionStatusUpdated`;\n payload: [\n {\n transactionMeta: TransactionMeta;\n },\n ];\n};\n\n/**\n * Represents the `TransactionController:transactionSubmitted` event.\n */\nexport type TransactionControllerTransactionSubmittedEvent = {\n type: `${typeof controllerName}:transactionSubmitted`;\n payload: [\n {\n transactionMeta: TransactionMeta;\n actionId?: string;\n },\n ];\n};\n\n/**\n * Represents the `TransactionController:unapprovedTransactionAdded` event.\n */\nexport type TransactionControllerUnapprovedTransactionAddedEvent = {\n type: `${typeof controllerName}:unapprovedTransactionAdded`;\n payload: [transactionMeta: TransactionMeta];\n};\n\n/**\n * The internal events available to the {@link TransactionController}.\n */\nexport type TransactionControllerEvents =\n | TransactionControllerIncomingTransactionBlockReceivedEvent\n | TransactionControllerPostTransactionBalanceUpdatedEvent\n | TransactionControllerSpeedupTransactionAddedEvent\n | TransactionControllerStateChangeEvent\n | TransactionControllerTransactionApprovedEvent\n | TransactionControllerTransactionConfirmedEvent\n | TransactionControllerTransactionDroppedEvent\n | TransactionControllerTransactionFailedEvent\n | TransactionControllerTransactionFinishedEvent\n | TransactionControllerTransactionNewSwapApprovalEvent\n | TransactionControllerTransactionNewSwapEvent\n | TransactionControllerTransactionNewSwapAndSendEvent\n | TransactionControllerTransactionPublishingSkipped\n | TransactionControllerTransactionRejectedEvent\n | TransactionControllerTransactionStatusUpdatedEvent\n | TransactionControllerTransactionSubmittedEvent\n | TransactionControllerUnapprovedTransactionAddedEvent;\n\n/**\n * The messenger of the {@link TransactionController}.\n */\nexport type TransactionControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n TransactionControllerActions | AllowedActions,\n TransactionControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\n/**\n * Possible states of the approve transaction step.\n */\nexport enum ApprovalState {\n Approved = 'approved',\n NotApproved = 'not-approved',\n SkippedViaBeforePublishHook = 'skipped-via-before-publish-hook',\n}\n\n/**\n * Get the default TransactionsController state.\n *\n * @returns The default TransactionsController state.\n */\nfunction getDefaultTransactionControllerState(): TransactionControllerState {\n return {\n methodData: {},\n transactions: [],\n lastFetchedBlockNumbers: {},\n };\n}\n\n/**\n * Controller responsible for submitting and managing transactions.\n */\nexport class TransactionController extends BaseController<\n typeof controllerName,\n TransactionControllerState,\n TransactionControllerMessenger\n> {\n #internalEvents = new EventEmitter();\n\n private readonly isHistoryDisabled: boolean;\n\n private readonly isSwapsDisabled: boolean;\n\n private readonly isSendFlowHistoryDisabled: boolean;\n\n private readonly approvingTransactionIds: Set = new Set();\n\n private readonly nonceTracker: NonceTracker;\n\n private readonly registry: MethodRegistry;\n\n private readonly mutex = new Mutex();\n\n private readonly gasFeeFlows: GasFeeFlow[];\n\n private readonly getSavedGasFees: (chainId: Hex) => SavedGasFees | undefined;\n\n private readonly getNetworkState: () => NetworkState;\n\n private readonly getCurrentAccountEIP1559Compatibility: () => Promise;\n\n private readonly getCurrentNetworkEIP1559Compatibility: (\n networkClientId?: NetworkClientId,\n ) => Promise;\n\n private readonly getGasFeeEstimates: (\n options: FetchGasFeeEstimateOptions,\n ) => Promise;\n\n private readonly getPermittedAccounts: (origin?: string) => Promise;\n\n private readonly getExternalPendingTransactions: (\n address: string,\n chainId?: string,\n ) => NonceTrackerTransaction[];\n\n private readonly layer1GasFeeFlows: Layer1GasFeeFlow[];\n\n readonly #incomingTransactionOptions: IncomingTransactionOptions;\n\n private readonly incomingTransactionHelper: IncomingTransactionHelper;\n\n private readonly securityProviderRequest?: SecurityProviderRequest;\n\n readonly #pendingTransactionOptions: PendingTransactionOptions;\n\n private readonly pendingTransactionTracker: PendingTransactionTracker;\n\n private readonly signAbortCallbacks: Map void> = new Map();\n\n #transactionHistoryLimit: number;\n\n #isSimulationEnabled: () => boolean;\n\n #testGasFeeFlows: boolean;\n\n private readonly afterSign: (\n transactionMeta: TransactionMeta,\n signedTx: TypedTransaction,\n ) => boolean;\n\n private readonly beforeCheckPendingTransaction: (\n transactionMeta: TransactionMeta,\n ) => boolean;\n\n private readonly beforePublish: (transactionMeta: TransactionMeta) => boolean;\n\n private readonly publish: (\n transactionMeta: TransactionMeta,\n rawTx: string,\n ) => Promise<{ transactionHash?: string }>;\n\n private readonly getAdditionalSignArguments: (\n transactionMeta: TransactionMeta,\n ) => (TransactionMeta | undefined)[];\n\n private failTransaction(\n transactionMeta: TransactionMeta,\n error: Error,\n actionId?: string,\n ) {\n let newTransactionMeta: TransactionMeta;\n\n try {\n newTransactionMeta = this.#updateTransactionInternal(\n {\n transactionId: transactionMeta.id,\n note: 'TransactionController#failTransaction - Add error message and set status to failed',\n skipValidation: true,\n },\n (draftTransactionMeta) => {\n draftTransactionMeta.status = TransactionStatus.failed;\n\n (\n draftTransactionMeta as TransactionMeta & {\n status: TransactionStatus.failed;\n }\n ).error = normalizeTxError(error);\n },\n );\n } catch (err: unknown) {\n log('Failed to mark transaction as failed', err);\n\n newTransactionMeta = {\n ...transactionMeta,\n status: TransactionStatus.failed,\n error: normalizeTxError(error),\n };\n }\n\n this.messagingSystem.publish(`${controllerName}:transactionFailed`, {\n actionId,\n error: error.message,\n transactionMeta: newTransactionMeta,\n });\n\n this.onTransactionStatusChange(newTransactionMeta);\n\n this.messagingSystem.publish(\n `${controllerName}:transactionFinished`,\n newTransactionMeta,\n );\n\n this.#internalEvents.emit(\n `${transactionMeta.id}:finished`,\n newTransactionMeta,\n );\n }\n\n private async registryLookup(fourBytePrefix: string): Promise {\n const registryMethod = await this.registry.lookup(fourBytePrefix);\n if (!registryMethod) {\n return {\n registryMethod: '',\n parsedRegistryMethod: { name: undefined, args: undefined },\n };\n }\n const parsedRegistryMethod = this.registry.parse(registryMethod);\n return { registryMethod, parsedRegistryMethod };\n }\n\n #multichainTrackingHelper: MultichainTrackingHelper;\n\n /**\n * Method used to sign transactions\n */\n sign?: (\n transaction: TypedTransaction,\n from: string,\n transactionMeta?: TransactionMeta,\n ) => Promise;\n\n /**\n * Constructs a TransactionController.\n *\n * @param options - The controller options.\n * @param options.blockTracker - The block tracker used to poll for new blocks data.\n * @param options.disableHistory - Whether to disable storing history in transaction metadata.\n * @param options.disableSendFlowHistory - Explicitly disable transaction metadata history.\n * @param options.disableSwaps - Whether to disable additional processing on swaps transactions.\n * @param options.getCurrentAccountEIP1559Compatibility - Whether or not the account supports EIP-1559.\n * @param options.getCurrentNetworkEIP1559Compatibility - Whether or not the network supports EIP-1559.\n * @param options.getExternalPendingTransactions - Callback to retrieve pending transactions from external sources.\n * @param options.getGasFeeEstimates - Callback to retrieve gas fee estimates.\n * @param options.getNetworkClientRegistry - Gets the network client registry.\n * @param options.getNetworkState - Gets the state of the network controller.\n * @param options.getPermittedAccounts - Get accounts that a given origin has permissions for.\n * @param options.getSavedGasFees - Gets the saved gas fee config.\n * @param options.incomingTransactions - Configuration options for incoming transaction support.\n * @param options.isMultichainEnabled - Enable multichain support.\n * @param options.isSimulationEnabled - Whether new transactions will be automatically simulated.\n * @param options.messenger - The controller messenger.\n * @param options.onNetworkStateChange - Allows subscribing to network controller state changes.\n * @param options.pendingTransactions - Configuration options for pending transaction support.\n * @param options.provider - The provider used to create the underlying EthQuery instance.\n * @param options.securityProviderRequest - A function for verifying a transaction, whether it is malicious or not.\n * @param options.sign - Function used to sign transactions.\n * @param options.state - Initial state to set on this controller.\n * @param options.testGasFeeFlows - Whether to use the test gas fee flow.\n * @param options.transactionHistoryLimit - Transaction history limit.\n * @param options.hooks - The controller hooks.\n */\n constructor({\n blockTracker,\n disableHistory,\n disableSendFlowHistory,\n disableSwaps,\n getCurrentAccountEIP1559Compatibility,\n getCurrentNetworkEIP1559Compatibility,\n getExternalPendingTransactions,\n getGasFeeEstimates,\n getNetworkClientRegistry,\n getNetworkState,\n getPermittedAccounts,\n getSavedGasFees,\n incomingTransactions = {},\n isMultichainEnabled = false,\n isSimulationEnabled,\n messenger,\n onNetworkStateChange,\n pendingTransactions = {},\n provider,\n securityProviderRequest,\n sign,\n state,\n testGasFeeFlows,\n transactionHistoryLimit = 40,\n hooks,\n }: TransactionControllerOptions) {\n super({\n name: controllerName,\n metadata,\n messenger,\n state: {\n ...getDefaultTransactionControllerState(),\n ...state,\n },\n });\n\n this.messagingSystem = messenger;\n this.getNetworkState = getNetworkState;\n this.isSendFlowHistoryDisabled = disableSendFlowHistory ?? false;\n this.isHistoryDisabled = disableHistory ?? false;\n this.isSwapsDisabled = disableSwaps ?? false;\n this.#isSimulationEnabled = isSimulationEnabled ?? (() => true);\n // @ts-expect-error the type in eth-method-registry is inappropriate and should be changed\n this.registry = new MethodRegistry({ provider });\n this.getSavedGasFees = getSavedGasFees ?? ((_chainId) => undefined);\n this.getCurrentAccountEIP1559Compatibility =\n getCurrentAccountEIP1559Compatibility ?? (() => Promise.resolve(true));\n this.getCurrentNetworkEIP1559Compatibility =\n getCurrentNetworkEIP1559Compatibility;\n this.getGasFeeEstimates =\n getGasFeeEstimates || (() => Promise.resolve({} as GasFeeState));\n this.getPermittedAccounts = getPermittedAccounts;\n this.getExternalPendingTransactions =\n getExternalPendingTransactions ?? (() => []);\n this.securityProviderRequest = securityProviderRequest;\n this.#incomingTransactionOptions = incomingTransactions;\n this.#pendingTransactionOptions = pendingTransactions;\n this.#transactionHistoryLimit = transactionHistoryLimit;\n this.sign = sign;\n this.#testGasFeeFlows = testGasFeeFlows === true;\n\n this.afterSign = hooks?.afterSign ?? (() => true);\n this.beforeCheckPendingTransaction =\n hooks?.beforeCheckPendingTransaction ??\n /* istanbul ignore next */\n (() => true);\n this.beforePublish = hooks?.beforePublish ?? (() => true);\n this.getAdditionalSignArguments =\n hooks?.getAdditionalSignArguments ?? (() => []);\n this.publish =\n hooks?.publish ?? (() => Promise.resolve({ transactionHash: undefined }));\n\n this.nonceTracker = this.#createNonceTracker({\n provider,\n blockTracker,\n });\n\n const findNetworkClientIdByChainId = (chainId: Hex) => {\n return this.messagingSystem.call(\n `NetworkController:findNetworkClientIdByChainId`,\n chainId,\n );\n };\n\n this.#multichainTrackingHelper = new MultichainTrackingHelper({\n isMultichainEnabled,\n provider,\n nonceTracker: this.nonceTracker,\n incomingTransactionOptions: incomingTransactions,\n findNetworkClientIdByChainId,\n getNetworkClientById: ((networkClientId: NetworkClientId) => {\n return this.messagingSystem.call(\n `NetworkController:getNetworkClientById`,\n networkClientId,\n );\n }) as NetworkController['getNetworkClientById'],\n getNetworkClientRegistry,\n removeIncomingTransactionHelperListeners:\n this.#removeIncomingTransactionHelperListeners.bind(this),\n removePendingTransactionTrackerListeners:\n this.#removePendingTransactionTrackerListeners.bind(this),\n createNonceTracker: this.#createNonceTracker.bind(this),\n createIncomingTransactionHelper:\n this.#createIncomingTransactionHelper.bind(this),\n createPendingTransactionTracker:\n this.#createPendingTransactionTracker.bind(this),\n onNetworkStateChange: (listener) => {\n this.messagingSystem.subscribe(\n 'NetworkController:stateChange',\n listener,\n );\n },\n });\n this.#multichainTrackingHelper.initialize();\n\n const etherscanRemoteTransactionSource =\n new EtherscanRemoteTransactionSource({\n includeTokenTransfers: incomingTransactions.includeTokenTransfers,\n });\n\n this.incomingTransactionHelper = this.#createIncomingTransactionHelper({\n blockTracker,\n etherscanRemoteTransactionSource,\n });\n\n this.pendingTransactionTracker = this.#createPendingTransactionTracker({\n provider,\n blockTracker,\n });\n\n this.gasFeeFlows = this.#getGasFeeFlows();\n this.layer1GasFeeFlows = this.#getLayer1GasFeeFlows();\n\n const gasFeePoller = new GasFeePoller({\n findNetworkClientIdByChainId,\n gasFeeFlows: this.gasFeeFlows,\n getGasFeeControllerEstimates: this.getGasFeeEstimates,\n getProvider: (chainId, networkClientId) =>\n this.#multichainTrackingHelper.getProvider({\n networkClientId,\n chainId,\n }),\n getTransactions: () => this.state.transactions,\n layer1GasFeeFlows: this.layer1GasFeeFlows,\n onStateChange: (listener) => {\n this.messagingSystem.subscribe(\n 'TransactionController:stateChange',\n listener,\n );\n },\n });\n\n gasFeePoller.hub.on(\n 'transaction-updated',\n this.#onGasFeePollerTransactionUpdate.bind(this),\n );\n\n // when transactionsController state changes\n // check for pending transactions and start polling if there are any\n this.messagingSystem.subscribe(\n 'TransactionController:stateChange',\n this.#checkForPendingTransactionAndStartPolling,\n );\n\n // TODO once v2 is merged make sure this only runs when\n // selectedNetworkClientId changes\n onNetworkStateChange(() => {\n log('Detected network change', this.getChainId());\n this.pendingTransactionTracker.startIfPendingTransactions();\n this.onBootCleanup();\n });\n\n this.onBootCleanup();\n this.#checkForPendingTransactionAndStartPolling();\n }\n\n /**\n * Stops polling and removes listeners to prepare the controller for garbage collection.\n */\n destroy() {\n this.#stopAllTracking();\n }\n\n /**\n * Handle new method data request.\n *\n * @param fourBytePrefix - The method prefix.\n * @returns The method data object corresponding to the given signature prefix.\n */\n async handleMethodData(fourBytePrefix: string): Promise {\n const releaseLock = await this.mutex.acquire();\n try {\n const { methodData } = this.state;\n const knownMethod = Object.keys(methodData).find(\n (knownFourBytePrefix) => fourBytePrefix === knownFourBytePrefix,\n );\n if (knownMethod) {\n return methodData[fourBytePrefix];\n }\n const registry = await this.registryLookup(fourBytePrefix);\n this.update((state) => {\n state.methodData[fourBytePrefix] = registry;\n });\n return registry;\n } finally {\n releaseLock();\n }\n }\n\n /**\n * Add a new unapproved transaction to state. Parameters will be validated, a\n * unique transaction id will be generated, and gas and gasPrice will be calculated\n * if not provided. If A `:unapproved` hub event will be emitted once added.\n *\n * @param txParams - Standard parameters for an Ethereum transaction.\n * @param opts - Additional options to control how the transaction is added.\n * @param opts.actionId - Unique ID to prevent duplicate requests.\n * @param opts.deviceConfirmedOn - An enum to indicate what device confirmed the transaction.\n * @param opts.method - RPC method that requested the transaction.\n * @param opts.origin - The origin of the transaction request, such as a dApp hostname.\n * @param opts.requireApproval - Whether the transaction requires approval by the user, defaults to true unless explicitly disabled.\n * @param opts.securityAlertResponse - Response from security validator.\n * @param opts.sendFlowHistory - The sendFlowHistory entries to add.\n * @param opts.type - Type of transaction to add, such as 'cancel' or 'swap'.\n * @param opts.swaps - Options for swaps transactions.\n * @param opts.swaps.hasApproveTx - Whether the transaction has an approval transaction.\n * @param opts.swaps.meta - Metadata for swap transaction.\n * @param opts.networkClientId - The id of the network client for this transaction.\n * @returns Object containing a promise resolving to the transaction hash if approved.\n */\n async addTransaction(\n txParams: TransactionParams,\n {\n actionId,\n deviceConfirmedOn,\n method,\n origin,\n requireApproval,\n securityAlertResponse,\n sendFlowHistory,\n swaps = {},\n type,\n networkClientId: requestNetworkClientId,\n }: {\n actionId?: string;\n deviceConfirmedOn?: WalletDevice;\n method?: string;\n origin?: string;\n requireApproval?: boolean | undefined;\n securityAlertResponse?: SecurityAlertResponse;\n sendFlowHistory?: SendFlowHistoryEntry[];\n swaps?: {\n hasApproveTx?: boolean;\n meta?: Partial;\n };\n type?: TransactionType;\n networkClientId?: NetworkClientId;\n } = {},\n ): Promise {\n log('Adding transaction', txParams);\n\n txParams = normalizeTransactionParams(txParams);\n if (\n requestNetworkClientId &&\n !this.#multichainTrackingHelper.has(requestNetworkClientId)\n ) {\n throw new Error(\n 'The networkClientId for this transaction could not be found',\n );\n }\n\n const networkClientId =\n requestNetworkClientId ?? this.#getGlobalNetworkClientId();\n\n const isEIP1559Compatible = await this.getEIP1559Compatibility(\n networkClientId,\n );\n\n validateTxParams(txParams, isEIP1559Compatible);\n\n if (origin) {\n await validateTransactionOrigin(\n await this.getPermittedAccounts(origin),\n this.#getSelectedAccount().address,\n txParams.from,\n origin,\n );\n }\n\n const dappSuggestedGasFees = this.generateDappSuggestedGasFees(\n txParams,\n origin,\n );\n\n const chainId = this.getChainId(networkClientId);\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId,\n chainId,\n });\n\n const transactionType =\n type ?? (await determineTransactionType(txParams, ethQuery)).type;\n\n const existingTransactionMeta = this.getTransactionWithActionId(actionId);\n\n // If a request to add a transaction with the same actionId is submitted again, a new transaction will not be created for it.\n let addedTransactionMeta = existingTransactionMeta\n ? cloneDeep(existingTransactionMeta)\n : {\n // Add actionId to txMeta to check if same actionId is seen again\n actionId,\n chainId,\n dappSuggestedGasFees,\n deviceConfirmedOn,\n id: random(),\n origin,\n securityAlertResponse,\n status: TransactionStatus.unapproved as const,\n time: Date.now(),\n txParams,\n userEditedGasLimit: false,\n verifiedOnBlockchain: false,\n type: transactionType,\n networkClientId,\n };\n\n await this.updateGasProperties(addedTransactionMeta);\n\n // Checks if a transaction already exists with a given actionId\n if (!existingTransactionMeta) {\n // Set security provider response\n if (method && this.securityProviderRequest) {\n const securityProviderResponse = await this.securityProviderRequest(\n addedTransactionMeta,\n method,\n );\n addedTransactionMeta.securityProviderResponse =\n securityProviderResponse;\n }\n\n if (!this.isSendFlowHistoryDisabled) {\n addedTransactionMeta.sendFlowHistory = sendFlowHistory ?? [];\n }\n // Initial history push\n if (!this.isHistoryDisabled) {\n addedTransactionMeta = addInitialHistorySnapshot(addedTransactionMeta);\n }\n\n addedTransactionMeta = updateSwapsTransaction(\n addedTransactionMeta,\n transactionType,\n swaps,\n {\n isSwapsDisabled: this.isSwapsDisabled,\n cancelTransaction: this.cancelTransaction.bind(this),\n messenger: this.messagingSystem,\n },\n );\n\n this.addMetadata(addedTransactionMeta);\n\n if (requireApproval !== false) {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#updateSimulationData(addedTransactionMeta);\n } else {\n log('Skipping simulation as approval not required');\n }\n\n this.messagingSystem.publish(\n `${controllerName}:unapprovedTransactionAdded`,\n addedTransactionMeta,\n );\n }\n\n return {\n result: this.processApproval(addedTransactionMeta, {\n isExisting: Boolean(existingTransactionMeta),\n requireApproval,\n actionId,\n }),\n transactionMeta: addedTransactionMeta,\n };\n }\n\n startIncomingTransactionPolling(networkClientIds: NetworkClientId[] = []) {\n if (networkClientIds.length === 0) {\n this.incomingTransactionHelper.start();\n return;\n }\n this.#multichainTrackingHelper.startIncomingTransactionPolling(\n networkClientIds,\n );\n }\n\n stopIncomingTransactionPolling(networkClientIds: NetworkClientId[] = []) {\n if (networkClientIds.length === 0) {\n this.incomingTransactionHelper.stop();\n return;\n }\n this.#multichainTrackingHelper.stopIncomingTransactionPolling(\n networkClientIds,\n );\n }\n\n stopAllIncomingTransactionPolling() {\n this.incomingTransactionHelper.stop();\n this.#multichainTrackingHelper.stopAllIncomingTransactionPolling();\n }\n\n async updateIncomingTransactions(networkClientIds: NetworkClientId[] = []) {\n if (networkClientIds.length === 0) {\n await this.incomingTransactionHelper.update();\n return;\n }\n await this.#multichainTrackingHelper.updateIncomingTransactions(\n networkClientIds,\n );\n }\n\n /**\n * Attempts to cancel a transaction based on its ID by setting its status to \"rejected\"\n * and emitting a `:finished` hub event.\n *\n * @param transactionId - The ID of the transaction to cancel.\n * @param gasValues - The gas values to use for the cancellation transaction.\n * @param options - The options for the cancellation transaction.\n * @param options.actionId - Unique ID to prevent duplicate requests.\n * @param options.estimatedBaseFee - The estimated base fee of the transaction.\n */\n async stopTransaction(\n transactionId: string,\n gasValues?: GasPriceValue | FeeMarketEIP1559Values,\n {\n estimatedBaseFee,\n actionId,\n }: { estimatedBaseFee?: string; actionId?: string } = {},\n ) {\n // If transaction is found for same action id, do not create a cancel transaction.\n if (this.getTransactionWithActionId(actionId)) {\n return;\n }\n\n if (gasValues) {\n // Not good practice to reassign a parameter but temporarily avoiding a larger refactor.\n gasValues = normalizeGasFeeValues(gasValues);\n validateGasValues(gasValues);\n }\n\n log('Creating cancel transaction', transactionId, gasValues);\n\n const transactionMeta = this.getTransaction(transactionId);\n if (!transactionMeta) {\n return;\n }\n\n if (!this.sign) {\n throw new Error('No sign method defined.');\n }\n\n // gasPrice (legacy non EIP1559)\n const minGasPrice = getIncreasedPriceFromExisting(\n transactionMeta.txParams.gasPrice,\n CANCEL_RATE,\n );\n\n const gasPriceFromValues = isGasPriceValue(gasValues) && gasValues.gasPrice;\n\n const newGasPrice =\n (gasPriceFromValues &&\n validateMinimumIncrease(gasPriceFromValues, minGasPrice)) ||\n minGasPrice;\n\n // maxFeePerGas (EIP1559)\n const existingMaxFeePerGas = transactionMeta.txParams?.maxFeePerGas;\n const minMaxFeePerGas = getIncreasedPriceFromExisting(\n existingMaxFeePerGas,\n CANCEL_RATE,\n );\n const maxFeePerGasValues =\n isFeeMarketEIP1559Values(gasValues) && gasValues.maxFeePerGas;\n const newMaxFeePerGas =\n (maxFeePerGasValues &&\n validateMinimumIncrease(maxFeePerGasValues, minMaxFeePerGas)) ||\n (existingMaxFeePerGas && minMaxFeePerGas);\n\n // maxPriorityFeePerGas (EIP1559)\n const existingMaxPriorityFeePerGas =\n transactionMeta.txParams?.maxPriorityFeePerGas;\n const minMaxPriorityFeePerGas = getIncreasedPriceFromExisting(\n existingMaxPriorityFeePerGas,\n CANCEL_RATE,\n );\n const maxPriorityFeePerGasValues =\n isFeeMarketEIP1559Values(gasValues) && gasValues.maxPriorityFeePerGas;\n const newMaxPriorityFeePerGas =\n (maxPriorityFeePerGasValues &&\n validateMinimumIncrease(\n maxPriorityFeePerGasValues,\n minMaxPriorityFeePerGas,\n )) ||\n (existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas);\n\n const newTxParams: TransactionParams =\n newMaxFeePerGas && newMaxPriorityFeePerGas\n ? {\n from: transactionMeta.txParams.from,\n gasLimit: transactionMeta.txParams.gas,\n maxFeePerGas: newMaxFeePerGas,\n maxPriorityFeePerGas: newMaxPriorityFeePerGas,\n type: TransactionEnvelopeType.feeMarket,\n nonce: transactionMeta.txParams.nonce,\n to: transactionMeta.txParams.from,\n value: '0x0',\n }\n : {\n from: transactionMeta.txParams.from,\n gasLimit: transactionMeta.txParams.gas,\n gasPrice: newGasPrice,\n nonce: transactionMeta.txParams.nonce,\n to: transactionMeta.txParams.from,\n value: '0x0',\n };\n\n const unsignedEthTx = this.prepareUnsignedEthTx(\n transactionMeta.chainId,\n newTxParams,\n );\n\n const signedTx = await this.sign(\n unsignedEthTx,\n transactionMeta.txParams.from,\n );\n\n const rawTx = bufferToHex(signedTx.serialize());\n\n const newFee = newTxParams.maxFeePerGas ?? newTxParams.gasPrice;\n\n const oldFee = newTxParams.maxFeePerGas\n ? transactionMeta.txParams.maxFeePerGas\n : transactionMeta.txParams.gasPrice;\n\n log('Submitting cancel transaction', {\n oldFee,\n newFee,\n txParams: newTxParams,\n });\n\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId: transactionMeta.networkClientId,\n chainId: transactionMeta.chainId,\n });\n const hash = await this.publishTransactionForRetry(\n ethQuery,\n rawTx,\n transactionMeta,\n );\n\n const cancelTransactionMeta = {\n actionId,\n chainId: transactionMeta.chainId,\n networkClientId: transactionMeta.networkClientId,\n estimatedBaseFee,\n hash,\n id: random(),\n originalGasEstimate: transactionMeta.txParams.gas,\n rawTx,\n status: TransactionStatus.submitted as const,\n time: Date.now(),\n type: TransactionType.cancel as const,\n txParams: newTxParams,\n };\n\n this.addMetadata(cancelTransactionMeta);\n\n // stopTransaction has no approval request, so we assume the user has already approved the transaction\n this.messagingSystem.publish(`${controllerName}:transactionApproved`, {\n transactionMeta: cancelTransactionMeta,\n actionId,\n });\n this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {\n transactionMeta: cancelTransactionMeta,\n actionId,\n });\n\n this.messagingSystem.publish(\n `${controllerName}:transactionFinished`,\n cancelTransactionMeta,\n );\n this.#internalEvents.emit(\n `${transactionMeta.id}:finished`,\n cancelTransactionMeta,\n );\n }\n\n /**\n * Attempts to speed up a transaction increasing transaction gasPrice by ten percent.\n *\n * @param transactionId - The ID of the transaction to speed up.\n * @param gasValues - The gas values to use for the speed up transaction.\n * @param options - The options for the speed up transaction.\n * @param options.actionId - Unique ID to prevent duplicate requests\n * @param options.estimatedBaseFee - The estimated base fee of the transaction.\n */\n async speedUpTransaction(\n transactionId: string,\n gasValues?: GasPriceValue | FeeMarketEIP1559Values,\n {\n actionId,\n estimatedBaseFee,\n }: { actionId?: string; estimatedBaseFee?: string } = {},\n ) {\n // If transaction is found for same action id, do not create a new speed up transaction.\n if (this.getTransactionWithActionId(actionId)) {\n return;\n }\n\n if (gasValues) {\n // Not good practice to reassign a parameter but temporarily avoiding a larger refactor.\n gasValues = normalizeGasFeeValues(gasValues);\n validateGasValues(gasValues);\n }\n\n log('Creating speed up transaction', transactionId, gasValues);\n\n const transactionMeta = this.getTransaction(transactionId);\n /* istanbul ignore next */\n if (!transactionMeta) {\n return;\n }\n\n /* istanbul ignore next */\n if (!this.sign) {\n throw new Error('No sign method defined.');\n }\n\n // gasPrice (legacy non EIP1559)\n const minGasPrice = getIncreasedPriceFromExisting(\n transactionMeta.txParams.gasPrice,\n SPEED_UP_RATE,\n );\n\n const gasPriceFromValues = isGasPriceValue(gasValues) && gasValues.gasPrice;\n\n const newGasPrice =\n (gasPriceFromValues &&\n validateMinimumIncrease(gasPriceFromValues, minGasPrice)) ||\n minGasPrice;\n\n // maxFeePerGas (EIP1559)\n const existingMaxFeePerGas = transactionMeta.txParams?.maxFeePerGas;\n const minMaxFeePerGas = getIncreasedPriceFromExisting(\n existingMaxFeePerGas,\n SPEED_UP_RATE,\n );\n const maxFeePerGasValues =\n isFeeMarketEIP1559Values(gasValues) && gasValues.maxFeePerGas;\n const newMaxFeePerGas =\n (maxFeePerGasValues &&\n validateMinimumIncrease(maxFeePerGasValues, minMaxFeePerGas)) ||\n (existingMaxFeePerGas && minMaxFeePerGas);\n\n // maxPriorityFeePerGas (EIP1559)\n const existingMaxPriorityFeePerGas =\n transactionMeta.txParams?.maxPriorityFeePerGas;\n const minMaxPriorityFeePerGas = getIncreasedPriceFromExisting(\n existingMaxPriorityFeePerGas,\n SPEED_UP_RATE,\n );\n const maxPriorityFeePerGasValues =\n isFeeMarketEIP1559Values(gasValues) && gasValues.maxPriorityFeePerGas;\n const newMaxPriorityFeePerGas =\n (maxPriorityFeePerGasValues &&\n validateMinimumIncrease(\n maxPriorityFeePerGasValues,\n minMaxPriorityFeePerGas,\n )) ||\n (existingMaxPriorityFeePerGas && minMaxPriorityFeePerGas);\n\n const txParams: TransactionParams =\n newMaxFeePerGas && newMaxPriorityFeePerGas\n ? {\n ...transactionMeta.txParams,\n gasLimit: transactionMeta.txParams.gas,\n maxFeePerGas: newMaxFeePerGas,\n maxPriorityFeePerGas: newMaxPriorityFeePerGas,\n type: TransactionEnvelopeType.feeMarket,\n }\n : {\n ...transactionMeta.txParams,\n gasLimit: transactionMeta.txParams.gas,\n gasPrice: newGasPrice,\n };\n\n const unsignedEthTx = this.prepareUnsignedEthTx(\n transactionMeta.chainId,\n txParams,\n );\n\n const signedTx = await this.sign(\n unsignedEthTx,\n transactionMeta.txParams.from,\n );\n\n const transactionMetaWithRsv = this.updateTransactionMetaRSV(\n transactionMeta,\n signedTx,\n );\n const rawTx = bufferToHex(signedTx.serialize());\n\n const newFee = txParams.maxFeePerGas ?? txParams.gasPrice;\n\n const oldFee = txParams.maxFeePerGas\n ? transactionMetaWithRsv.txParams.maxFeePerGas\n : transactionMetaWithRsv.txParams.gasPrice;\n\n log('Submitting speed up transaction', { oldFee, newFee, txParams });\n\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId: transactionMeta.networkClientId,\n chainId: transactionMeta.chainId,\n });\n const hash = await this.publishTransactionForRetry(\n ethQuery,\n rawTx,\n transactionMeta,\n );\n\n const baseTransactionMeta = {\n ...transactionMetaWithRsv,\n estimatedBaseFee,\n id: random(),\n time: Date.now(),\n hash,\n actionId,\n originalGasEstimate: transactionMeta.txParams.gas,\n type: TransactionType.retry as const,\n originalType: transactionMeta.type,\n };\n\n const newTransactionMeta =\n newMaxFeePerGas && newMaxPriorityFeePerGas\n ? {\n ...baseTransactionMeta,\n txParams: {\n ...transactionMeta.txParams,\n maxFeePerGas: newMaxFeePerGas,\n maxPriorityFeePerGas: newMaxPriorityFeePerGas,\n },\n }\n : {\n ...baseTransactionMeta,\n txParams: {\n ...transactionMeta.txParams,\n gasPrice: newGasPrice,\n },\n };\n\n this.addMetadata(newTransactionMeta);\n\n // speedUpTransaction has no approval request, so we assume the user has already approved the transaction\n this.messagingSystem.publish(`${controllerName}:transactionApproved`, {\n transactionMeta: newTransactionMeta,\n actionId,\n });\n\n this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {\n transactionMeta: newTransactionMeta,\n actionId,\n });\n\n this.messagingSystem.publish(\n `${controllerName}:speedupTransactionAdded`,\n newTransactionMeta,\n );\n }\n\n /**\n * Estimates required gas for a given transaction.\n *\n * @param transaction - The transaction to estimate gas for.\n * @param networkClientId - The network client id to use for the estimate.\n * @returns The gas and gas price.\n */\n async estimateGas(\n transaction: TransactionParams,\n networkClientId?: NetworkClientId,\n ) {\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId,\n });\n const { estimatedGas, simulationFails } = await estimateGas(\n transaction,\n ethQuery,\n );\n\n return { gas: estimatedGas, simulationFails };\n }\n\n /**\n * Estimates required gas for a given transaction and add additional gas buffer with the given multiplier.\n *\n * @param transaction - The transaction params to estimate gas for.\n * @param multiplier - The multiplier to use for the gas buffer.\n * @param networkClientId - The network client id to use for the estimate.\n */\n async estimateGasBuffered(\n transaction: TransactionParams,\n multiplier: number,\n networkClientId?: NetworkClientId,\n ) {\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId,\n });\n const { blockGasLimit, estimatedGas, simulationFails } = await estimateGas(\n transaction,\n ethQuery,\n );\n\n const gas = addGasBuffer(estimatedGas, blockGasLimit, multiplier);\n\n return {\n gas,\n simulationFails,\n };\n }\n\n /**\n * Updates an existing transaction in state.\n *\n * @param transactionMeta - The new transaction to store in state.\n * @param note - A note or update reason to include in the transaction history.\n */\n updateTransaction(transactionMeta: TransactionMeta, note: string) {\n const { id: transactionId } = transactionMeta;\n\n this.#updateTransactionInternal({ transactionId, note }, () => ({\n ...transactionMeta,\n }));\n }\n\n /**\n * Update the security alert response for a transaction.\n *\n * @param transactionId - ID of the transaction.\n * @param securityAlertResponse - The new security alert response for the transaction.\n */\n updateSecurityAlertResponse(\n transactionId: string,\n securityAlertResponse: SecurityAlertResponse,\n ) {\n if (!securityAlertResponse) {\n throw new Error(\n 'updateSecurityAlertResponse: securityAlertResponse should not be null',\n );\n }\n const transactionMeta = this.getTransaction(transactionId);\n if (!transactionMeta) {\n throw new Error(\n `Cannot update security alert response as no transaction metadata found`,\n );\n }\n const updatedTransactionMeta = {\n ...transactionMeta,\n securityAlertResponse,\n };\n this.updateTransaction(\n updatedTransactionMeta,\n `${controllerName}:updatesecurityAlertResponse - securityAlertResponse updated`,\n );\n }\n\n /**\n * Removes all transactions from state, optionally based on the current network.\n *\n * @param ignoreNetwork - Determines whether to wipe all transactions, or just those on the\n * current network. If `true`, all transactions are wiped.\n * @param address - If specified, only transactions originating from this address will be\n * wiped on current network.\n */\n wipeTransactions(ignoreNetwork?: boolean, address?: string) {\n /* istanbul ignore next */\n if (ignoreNetwork && !address) {\n this.update((state) => {\n state.transactions = [];\n });\n return;\n }\n const currentChainId = this.getChainId();\n const newTransactions = this.state.transactions.filter(\n ({ chainId, txParams }) => {\n const isMatchingNetwork = ignoreNetwork || chainId === currentChainId;\n\n if (!isMatchingNetwork) {\n return true;\n }\n\n const isMatchingAddress =\n !address || txParams.from?.toLowerCase() === address.toLowerCase();\n\n return !isMatchingAddress;\n },\n );\n\n this.update((state) => {\n state.transactions = this.trimTransactionsForState(newTransactions);\n });\n }\n\n /**\n * Adds external provided transaction to state as confirmed transaction.\n *\n * @param transactionMeta - TransactionMeta to add transactions.\n * @param transactionReceipt - TransactionReceipt of the external transaction.\n * @param baseFeePerGas - Base fee per gas of the external transaction.\n */\n async confirmExternalTransaction(\n transactionMeta: TransactionMeta,\n transactionReceipt: TransactionReceipt,\n baseFeePerGas: Hex,\n ) {\n // Run validation and add external transaction to state.\n const newTransactionMeta = this.addExternalTransaction(transactionMeta);\n\n try {\n const transactionId = newTransactionMeta.id;\n\n // Make sure status is confirmed and define gasUsed as in receipt.\n const updatedTransactionMeta = {\n ...newTransactionMeta,\n status: TransactionStatus.confirmed as const,\n txReceipt: transactionReceipt,\n };\n if (baseFeePerGas) {\n updatedTransactionMeta.baseFeePerGas = baseFeePerGas;\n }\n\n // Update same nonce local transactions as dropped and define replacedBy properties.\n this.markNonceDuplicatesDropped(transactionId);\n\n // Update external provided transaction with updated gas values and confirmed status.\n this.updateTransaction(\n updatedTransactionMeta,\n `${controllerName}:confirmExternalTransaction - Add external transaction`,\n );\n this.onTransactionStatusChange(updatedTransactionMeta);\n\n // Intentional given potential duration of process.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.updatePostBalance(updatedTransactionMeta);\n\n this.messagingSystem.publish(\n `${controllerName}:transactionConfirmed`,\n updatedTransactionMeta,\n );\n } catch (error) {\n console.error('Failed to confirm external transaction', error);\n }\n }\n\n /**\n * Append new send flow history to a transaction.\n *\n * @param transactionID - The ID of the transaction to update.\n * @param currentSendFlowHistoryLength - The length of the current sendFlowHistory array.\n * @param sendFlowHistoryToAdd - The sendFlowHistory entries to add.\n * @returns The updated transactionMeta.\n */\n updateTransactionSendFlowHistory(\n transactionID: string,\n currentSendFlowHistoryLength: number,\n sendFlowHistoryToAdd: SendFlowHistoryEntry[],\n ): TransactionMeta {\n if (this.isSendFlowHistoryDisabled) {\n throw new Error(\n 'Send flow history is disabled for the current transaction controller',\n );\n }\n\n const transactionMeta = this.getTransaction(transactionID);\n\n if (!transactionMeta) {\n throw new Error(\n `Cannot update send flow history as no transaction metadata found`,\n );\n }\n\n validateIfTransactionUnapproved(\n transactionMeta,\n 'updateTransactionSendFlowHistory',\n );\n\n const sendFlowHistory = transactionMeta.sendFlowHistory ?? [];\n if (currentSendFlowHistoryLength === sendFlowHistory.length) {\n const updatedTransactionMeta = {\n ...transactionMeta,\n sendFlowHistory: [...sendFlowHistory, ...sendFlowHistoryToAdd],\n };\n this.updateTransaction(\n updatedTransactionMeta,\n `${controllerName}:updateTransactionSendFlowHistory - sendFlowHistory updated`,\n );\n }\n\n return this.getTransaction(transactionID) as TransactionMeta;\n }\n\n /**\n * Update the gas values of a transaction.\n *\n * @param transactionId - The ID of the transaction to update.\n * @param gasValues - Gas values to update.\n * @param gasValues.gas - Same as transaction.gasLimit.\n * @param gasValues.gasLimit - Maxmimum number of units of gas to use for this transaction.\n * @param gasValues.gasPrice - Price per gas for legacy transactions.\n * @param gasValues.maxPriorityFeePerGas - Maximum amount per gas to give to validator as incentive.\n * @param gasValues.maxFeePerGas - Maximum amount per gas to pay for the transaction, including the priority fee.\n * @param gasValues.estimateUsed - Which estimate level was used.\n * @param gasValues.estimateSuggested - Which estimate level that the API suggested.\n * @param gasValues.defaultGasEstimates - The default estimate for gas.\n * @param gasValues.originalGasEstimate - Original estimate for gas.\n * @param gasValues.userEditedGasLimit - The gas limit supplied by user.\n * @param gasValues.userFeeLevel - Estimate level user selected.\n * @returns The updated transactionMeta.\n */\n updateTransactionGasFees(\n transactionId: string,\n {\n defaultGasEstimates,\n estimateUsed,\n estimateSuggested,\n gas,\n gasLimit,\n gasPrice,\n maxPriorityFeePerGas,\n maxFeePerGas,\n originalGasEstimate,\n userEditedGasLimit,\n userFeeLevel,\n }: {\n defaultGasEstimates?: string;\n estimateUsed?: string;\n estimateSuggested?: string;\n gas?: string;\n gasLimit?: string;\n gasPrice?: string;\n maxPriorityFeePerGas?: string;\n maxFeePerGas?: string;\n originalGasEstimate?: string;\n userEditedGasLimit?: boolean;\n userFeeLevel?: string;\n },\n ): TransactionMeta {\n const transactionMeta = this.getTransaction(transactionId);\n\n if (!transactionMeta) {\n throw new Error(\n `Cannot update transaction as no transaction metadata found`,\n );\n }\n\n validateIfTransactionUnapproved(\n transactionMeta,\n 'updateTransactionGasFees',\n );\n\n let transactionGasFees = {\n txParams: {\n gas,\n gasLimit,\n gasPrice,\n maxPriorityFeePerGas,\n maxFeePerGas,\n },\n defaultGasEstimates,\n estimateUsed,\n estimateSuggested,\n originalGasEstimate,\n userEditedGasLimit,\n userFeeLevel,\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n\n // only update what is defined\n transactionGasFees.txParams = pickBy(transactionGasFees.txParams);\n transactionGasFees = pickBy(transactionGasFees);\n\n // merge updated gas values with existing transaction meta\n const updatedMeta = merge({}, transactionMeta, transactionGasFees);\n\n this.updateTransaction(\n updatedMeta,\n `${controllerName}:updateTransactionGasFees - gas values updated`,\n );\n\n return this.getTransaction(transactionId) as TransactionMeta;\n }\n\n /**\n * Update the previous gas values of a transaction.\n *\n * @param transactionId - The ID of the transaction to update.\n * @param previousGas - Previous gas values to update.\n * @param previousGas.gasLimit - Maxmimum number of units of gas to use for this transaction.\n * @param previousGas.maxFeePerGas - Maximum amount per gas to pay for the transaction, including the priority fee.\n * @param previousGas.maxPriorityFeePerGas - Maximum amount per gas to give to validator as incentive.\n * @returns The updated transactionMeta.\n */\n updatePreviousGasParams(\n transactionId: string,\n {\n gasLimit,\n maxFeePerGas,\n maxPriorityFeePerGas,\n }: {\n gasLimit?: string;\n maxFeePerGas?: string;\n maxPriorityFeePerGas?: string;\n },\n ): TransactionMeta {\n const transactionMeta = this.getTransaction(transactionId);\n\n if (!transactionMeta) {\n throw new Error(\n `Cannot update transaction as no transaction metadata found`,\n );\n }\n\n validateIfTransactionUnapproved(transactionMeta, 'updatePreviousGasParams');\n\n const transactionPreviousGas = {\n previousGas: {\n gasLimit,\n maxFeePerGas,\n maxPriorityFeePerGas,\n },\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any;\n\n // only update what is defined\n transactionPreviousGas.previousGas = pickBy(\n transactionPreviousGas.previousGas,\n );\n\n // merge updated previous gas values with existing transaction meta\n const updatedMeta = merge({}, transactionMeta, transactionPreviousGas);\n\n this.updateTransaction(\n updatedMeta,\n `${controllerName}:updatePreviousGasParams - Previous gas values updated`,\n );\n\n return this.getTransaction(transactionId) as TransactionMeta;\n }\n\n async getNonceLock(\n address: string,\n networkClientId?: NetworkClientId,\n ): Promise {\n return this.#multichainTrackingHelper.getNonceLock(\n address,\n networkClientId,\n );\n }\n\n /**\n * Updates the editable parameters of a transaction.\n *\n * @param txId - The ID of the transaction to update.\n * @param params - The editable parameters to update.\n * @param params.data - Data to pass with the transaction.\n * @param params.gas - Maximum number of units of gas to use for the transaction.\n * @param params.gasPrice - Price per gas for legacy transactions.\n * @param params.from - Address to send the transaction from.\n * @param params.to - Address to send the transaction to.\n * @param params.value - Value associated with the transaction.\n * @returns The updated transaction metadata.\n */\n async updateEditableParams(\n txId: string,\n {\n data,\n gas,\n gasPrice,\n from,\n to,\n value,\n }: {\n data?: string;\n gas?: string;\n gasPrice?: string;\n from?: string;\n to?: string;\n value?: string;\n },\n ) {\n const transactionMeta = this.getTransaction(txId);\n if (!transactionMeta) {\n throw new Error(\n `Cannot update editable params as no transaction metadata found`,\n );\n }\n\n validateIfTransactionUnapproved(transactionMeta, 'updateEditableParams');\n\n const editableParams = {\n txParams: {\n data,\n from,\n to,\n value,\n gas,\n gasPrice,\n },\n } as Partial;\n\n editableParams.txParams = pickBy(\n editableParams.txParams,\n ) as TransactionParams;\n\n const updatedTransaction = merge({}, transactionMeta, editableParams);\n const provider = this.#multichainTrackingHelper.getProvider({\n chainId: transactionMeta.chainId,\n networkClientId: transactionMeta.networkClientId,\n });\n const ethQuery = new EthQuery(provider);\n const { type } = await determineTransactionType(\n updatedTransaction.txParams,\n ethQuery,\n );\n updatedTransaction.type = type;\n\n await updateTransactionLayer1GasFee({\n layer1GasFeeFlows: this.layer1GasFeeFlows,\n provider,\n transactionMeta: updatedTransaction,\n });\n\n this.updateTransaction(\n updatedTransaction,\n `Update Editable Params for ${txId}`,\n );\n return this.getTransaction(txId);\n }\n\n /**\n * Signs and returns the raw transaction data for provided transaction params list.\n *\n * @param listOfTxParams - The list of transaction params to approve.\n * @param opts - Options bag.\n * @param opts.hasNonce - Whether the transactions already have a nonce.\n * @returns The raw transactions.\n */\n async approveTransactionsWithSameNonce(\n listOfTxParams: (TransactionParams & { chainId: Hex })[] = [],\n { hasNonce }: { hasNonce?: boolean } = {},\n ): Promise {\n log('Approving transactions with same nonce', {\n transactions: listOfTxParams,\n });\n\n if (listOfTxParams.length === 0) {\n return '';\n }\n\n const initialTx = listOfTxParams[0];\n const common = this.getCommonConfiguration(initialTx.chainId);\n\n // We need to ensure we get the nonce using the the NonceTracker on the chain matching\n // the txParams. In this context we only have chainId available to us, but the\n // NonceTrackers are keyed by networkClientId. To workaround this, we attempt to find\n // a networkClientId that matches the chainId. As a fallback, the globally selected\n // network's NonceTracker will be used instead.\n let networkClientId: NetworkClientId | undefined;\n try {\n networkClientId = this.messagingSystem.call(\n `NetworkController:findNetworkClientIdByChainId`,\n initialTx.chainId,\n );\n } catch (err) {\n log('failed to find networkClientId from chainId', err);\n }\n\n const initialTxAsEthTx = TransactionFactory.fromTxData(initialTx, {\n common,\n });\n const initialTxAsSerializedHex = bufferToHex(initialTxAsEthTx.serialize());\n\n if (this.approvingTransactionIds.has(initialTxAsSerializedHex)) {\n return '';\n }\n this.approvingTransactionIds.add(initialTxAsSerializedHex);\n\n let rawTransactions, nonceLock;\n try {\n // TODO: we should add a check to verify that all transactions have the same from address\n const fromAddress = initialTx.from;\n const requiresNonce = hasNonce !== true;\n\n nonceLock = requiresNonce\n ? await this.getNonceLock(fromAddress, networkClientId)\n : undefined;\n\n const nonce = nonceLock\n ? add0x(nonceLock.nextNonce.toString(16))\n : initialTx.nonce;\n\n if (nonceLock) {\n log('Using nonce from nonce tracker', nonce, nonceLock.nonceDetails);\n }\n\n rawTransactions = await Promise.all(\n listOfTxParams.map((txParams) => {\n txParams.nonce = nonce;\n return this.signExternalTransaction(txParams.chainId, txParams);\n }),\n );\n } catch (err) {\n log('Error while signing transactions with same nonce', err);\n // Must set transaction to submitted/failed before releasing lock\n // continue with error chain\n throw err;\n } finally {\n nonceLock?.releaseLock();\n this.approvingTransactionIds.delete(initialTxAsSerializedHex);\n }\n return rawTransactions;\n }\n\n /**\n * Update a custodial transaction.\n *\n * @param transactionId - The ID of the transaction to update.\n * @param options - The custodial transaction options to update.\n * @param options.errorMessage - The error message to be assigned in case transaction status update to failed.\n * @param options.hash - The new hash value to be assigned.\n * @param options.status - The new status value to be assigned.\n */\n updateCustodialTransaction(\n transactionId: string,\n {\n errorMessage,\n hash,\n status,\n }: {\n errorMessage?: string;\n hash?: string;\n status?: TransactionStatus;\n },\n ) {\n const transactionMeta = this.getTransaction(transactionId);\n\n if (!transactionMeta) {\n throw new Error(\n `Cannot update custodial transaction as no transaction metadata found`,\n );\n }\n\n if (!transactionMeta.custodyId) {\n throw new Error('Transaction must be a custodian transaction');\n }\n\n if (\n status &&\n ![\n TransactionStatus.submitted,\n TransactionStatus.signed,\n TransactionStatus.failed,\n ].includes(status)\n ) {\n throw new Error(\n `Cannot update custodial transaction with status: ${status}`,\n );\n }\n\n const updatedTransactionMeta = merge(\n {},\n transactionMeta,\n pickBy({ hash, status }),\n ) as TransactionMeta;\n\n if (updatedTransactionMeta.status === TransactionStatus.submitted) {\n updatedTransactionMeta.submittedTime = new Date().getTime();\n }\n\n if (updatedTransactionMeta.status === TransactionStatus.failed) {\n updatedTransactionMeta.error = normalizeTxError(new Error(errorMessage));\n }\n\n this.updateTransaction(\n updatedTransactionMeta,\n `${controllerName}:updateCustodialTransaction - Custodial transaction updated`,\n );\n\n if (\n [TransactionStatus.submitted, TransactionStatus.failed].includes(\n status as TransactionStatus,\n )\n ) {\n this.messagingSystem.publish(\n `${controllerName}:transactionFinished`,\n updatedTransactionMeta,\n );\n this.#internalEvents.emit(\n `${updatedTransactionMeta.id}:finished`,\n updatedTransactionMeta,\n );\n }\n }\n\n /**\n * Search transaction metadata for matching entries.\n *\n * @param opts - Options bag.\n * @param opts.searchCriteria - An object containing values or functions for transaction properties to filter transactions with.\n * @param opts.initialList - The transactions to search. Defaults to the current state.\n * @param opts.filterToCurrentNetwork - Whether to filter the results to the current network. Defaults to true.\n * @param opts.limit - The maximum number of transactions to return. No limit by default.\n * @returns An array of transactions matching the provided options.\n */\n getTransactions({\n searchCriteria = {},\n initialList,\n filterToCurrentNetwork = true,\n limit,\n }: {\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n searchCriteria?: any;\n initialList?: TransactionMeta[];\n filterToCurrentNetwork?: boolean;\n limit?: number;\n } = {}): TransactionMeta[] {\n const chainId = this.getChainId();\n // searchCriteria is an object that might have values that aren't predicate\n // methods. When providing any other value type (string, number, etc), we\n // consider this shorthand for \"check the value at key for strict equality\n // with the provided value\". To conform this object to be only methods, we\n // mapValues (lodash) such that every value on the object is a method that\n // returns a boolean.\n const predicateMethods = mapValues(searchCriteria, (predicate) => {\n return typeof predicate === 'function'\n ? predicate\n : // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (v: any) => v === predicate;\n });\n\n const transactionsToFilter = initialList ?? this.state.transactions;\n\n // Combine sortBy and pickBy to transform our state object into an array of\n // matching transactions that are sorted by time.\n const filteredTransactions = sortBy(\n pickBy(transactionsToFilter, (transaction) => {\n if (filterToCurrentNetwork && transaction.chainId !== chainId) {\n return false;\n }\n // iterate over the predicateMethods keys to check if the transaction\n // matches the searchCriteria\n for (const [key, predicate] of Object.entries(predicateMethods)) {\n // We return false early as soon as we know that one of the specified\n // search criteria do not match the transaction. This prevents\n // needlessly checking all criteria when we already know the criteria\n // are not fully satisfied. We check both txParams and the base\n // object as predicate keys can be either.\n if (key in transaction.txParams) {\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (predicate((transaction.txParams as any)[key]) === false) {\n return false;\n }\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } else if (predicate((transaction as any)[key]) === false) {\n return false;\n }\n }\n\n return true;\n }),\n 'time',\n );\n if (limit !== undefined) {\n // We need to have all transactions of a given nonce in order to display\n // necessary details in the UI. We use the size of this set to determine\n // whether we have reached the limit provided, thus ensuring that all\n // transactions of nonces we include will be sent to the UI.\n const nonces = new Set();\n const txs = [];\n // By default, the transaction list we filter from is sorted by time ASC.\n // To ensure that filtered results prefers the newest transactions we\n // iterate from right to left, inserting transactions into front of a new\n // array. The original order is preserved, but we ensure that newest txs\n // are preferred.\n for (let i = filteredTransactions.length - 1; i > -1; i--) {\n const txMeta = filteredTransactions[i];\n const { nonce } = txMeta.txParams;\n if (!nonces.has(nonce)) {\n if (nonces.size < limit) {\n nonces.add(nonce);\n } else {\n continue;\n }\n }\n // Push transaction into the beginning of our array to ensure the\n // original order is preserved.\n txs.unshift(txMeta);\n }\n return txs;\n }\n return filteredTransactions;\n }\n\n async estimateGasFee({\n transactionParams,\n chainId,\n networkClientId: requestNetworkClientId,\n }: {\n transactionParams: TransactionParams;\n chainId?: Hex;\n networkClientId?: NetworkClientId;\n }): Promise {\n const networkClientId = this.#getNetworkClientId({\n networkClientId: requestNetworkClientId,\n chainId,\n });\n\n const transactionMeta = {\n txParams: transactionParams,\n chainId,\n networkClientId,\n } as TransactionMeta;\n\n // Guaranteed as the default gas fee flow matches all transactions.\n const gasFeeFlow = getGasFeeFlow(\n transactionMeta,\n this.gasFeeFlows,\n ) as GasFeeFlow;\n\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId,\n chainId,\n });\n\n const gasFeeControllerData = await this.getGasFeeEstimates({\n networkClientId,\n });\n\n return gasFeeFlow.getGasFees({\n ethQuery,\n gasFeeControllerData,\n transactionMeta,\n });\n }\n\n /**\n * Determine the layer 1 gas fee for the given transaction parameters.\n *\n * @param request - The request object.\n * @param request.transactionParams - The transaction parameters to estimate the layer 1 gas fee for.\n * @param request.chainId - The ID of the chain where the transaction will be executed.\n * @param request.networkClientId - The ID of a specific network client to process the transaction.\n */\n async getLayer1GasFee({\n transactionParams,\n chainId,\n networkClientId,\n }: {\n transactionParams: TransactionParams;\n chainId?: Hex;\n networkClientId?: NetworkClientId;\n }): Promise {\n const provider = this.#multichainTrackingHelper.getProvider({\n networkClientId,\n chainId,\n });\n\n return await getTransactionLayer1GasFee({\n layer1GasFeeFlows: this.layer1GasFeeFlows,\n provider,\n transactionMeta: {\n txParams: transactionParams,\n chainId,\n } as TransactionMeta,\n });\n }\n\n private async signExternalTransaction(\n chainId: Hex,\n transactionParams: TransactionParams,\n ): Promise {\n if (!this.sign) {\n throw new Error('No sign method defined.');\n }\n\n const normalizedTransactionParams =\n normalizeTransactionParams(transactionParams);\n const type = isEIP1559Transaction(normalizedTransactionParams)\n ? TransactionEnvelopeType.feeMarket\n : TransactionEnvelopeType.legacy;\n const updatedTransactionParams = {\n ...normalizedTransactionParams,\n type,\n gasLimit: normalizedTransactionParams.gas,\n chainId,\n };\n\n const { from } = updatedTransactionParams;\n const common = this.getCommonConfiguration(chainId);\n const unsignedTransaction = TransactionFactory.fromTxData(\n updatedTransactionParams,\n { common },\n );\n const signedTransaction = await this.sign(unsignedTransaction, from);\n\n const rawTransaction = bufferToHex(signedTransaction.serialize());\n return rawTransaction;\n }\n\n /**\n * Removes unapproved transactions from state.\n */\n clearUnapprovedTransactions() {\n const transactions = this.state.transactions.filter(\n ({ status }) => status !== TransactionStatus.unapproved,\n );\n this.update((state) => {\n state.transactions = this.trimTransactionsForState(transactions);\n });\n }\n\n /**\n * Stop the signing process for a specific transaction.\n * Throws an error causing the transaction status to be set to failed.\n * @param transactionId - The ID of the transaction to stop signing.\n */\n abortTransactionSigning(transactionId: string) {\n const transactionMeta = this.getTransaction(transactionId);\n\n if (!transactionMeta) {\n throw new Error(`Cannot abort signing as no transaction metadata found`);\n }\n\n const abortCallback = this.signAbortCallbacks.get(transactionId);\n\n if (!abortCallback) {\n throw new Error(\n `Cannot abort signing as transaction is not waiting for signing`,\n );\n }\n\n abortCallback();\n\n this.signAbortCallbacks.delete(transactionId);\n }\n\n private addMetadata(transactionMeta: TransactionMeta) {\n this.update((state) => {\n state.transactions = this.trimTransactionsForState([\n ...state.transactions,\n transactionMeta,\n ]);\n });\n }\n\n private async updateGasProperties(transactionMeta: TransactionMeta) {\n const isEIP1559Compatible =\n (await this.getEIP1559Compatibility(transactionMeta.networkClientId)) &&\n transactionMeta.txParams.type !== TransactionEnvelopeType.legacy;\n\n const { networkClientId, chainId } = transactionMeta;\n\n const isCustomNetwork = this.#isCustomNetwork(networkClientId);\n\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId,\n chainId,\n });\n\n const provider = this.#multichainTrackingHelper.getProvider({\n networkClientId,\n chainId,\n });\n\n await updateGas({\n ethQuery,\n chainId,\n isCustomNetwork,\n txMeta: transactionMeta,\n });\n\n await updateGasFees({\n eip1559: isEIP1559Compatible,\n ethQuery,\n gasFeeFlows: this.gasFeeFlows,\n getGasFeeEstimates: this.getGasFeeEstimates,\n getSavedGasFees: this.getSavedGasFees.bind(this),\n txMeta: transactionMeta,\n });\n\n await updateTransactionLayer1GasFee({\n layer1GasFeeFlows: this.layer1GasFeeFlows,\n provider,\n transactionMeta,\n });\n }\n\n private onBootCleanup() {\n this.clearUnapprovedTransactions();\n this.failIncompleteTransactions();\n }\n\n private failIncompleteTransactions() {\n const incompleteTransactions = this.state.transactions.filter(\n (transaction) =>\n [TransactionStatus.approved, TransactionStatus.signed].includes(\n transaction.status,\n ),\n );\n\n for (const transactionMeta of incompleteTransactions) {\n this.failTransaction(\n transactionMeta,\n new Error('Transaction incomplete at startup'),\n );\n }\n }\n\n private async processApproval(\n transactionMeta: TransactionMeta,\n {\n isExisting = false,\n requireApproval,\n shouldShowRequest = true,\n actionId,\n }: {\n isExisting?: boolean;\n requireApproval?: boolean | undefined;\n shouldShowRequest?: boolean;\n actionId?: string;\n },\n ): Promise {\n const transactionId = transactionMeta.id;\n let resultCallbacks: AcceptResultCallbacks | undefined;\n const { meta, isCompleted } = this.isTransactionCompleted(transactionId);\n const finishedPromise = isCompleted\n ? Promise.resolve(meta)\n : this.waitForTransactionFinished(transactionId);\n\n if (meta && !isExisting && !isCompleted) {\n try {\n if (requireApproval !== false) {\n const acceptResult = await this.requestApproval(transactionMeta, {\n shouldShowRequest,\n });\n resultCallbacks = acceptResult.resultCallbacks;\n\n const approvalValue = acceptResult.value as\n | {\n txMeta?: TransactionMeta;\n }\n | undefined;\n\n const updatedTransaction = approvalValue?.txMeta;\n\n if (updatedTransaction) {\n log('Updating transaction with approval data', {\n customNonce: updatedTransaction.customNonceValue,\n params: updatedTransaction.txParams,\n });\n\n this.updateTransaction(\n updatedTransaction,\n 'TransactionController#processApproval - Updated with approval data',\n );\n }\n }\n\n const { isCompleted: isTxCompleted } =\n this.isTransactionCompleted(transactionId);\n\n if (!isTxCompleted) {\n const approvalResult = await this.approveTransaction(transactionId);\n if (\n approvalResult === ApprovalState.SkippedViaBeforePublishHook &&\n resultCallbacks\n ) {\n resultCallbacks.success();\n }\n const updatedTransactionMeta = this.getTransaction(\n transactionId,\n ) as TransactionMeta;\n this.messagingSystem.publish(\n `${controllerName}:transactionApproved`,\n {\n transactionMeta: updatedTransactionMeta,\n actionId,\n },\n );\n }\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n const { isCompleted: isTxCompleted } =\n this.isTransactionCompleted(transactionId);\n if (!isTxCompleted) {\n if (error?.code === errorCodes.provider.userRejectedRequest) {\n this.cancelTransaction(transactionId, actionId);\n\n throw providerErrors.userRejectedRequest(\n 'MetaMask Tx Signature: User denied transaction signature.',\n );\n } else {\n this.failTransaction(meta, error, actionId);\n }\n }\n }\n }\n\n const finalMeta = await finishedPromise;\n\n switch (finalMeta?.status) {\n case TransactionStatus.failed:\n resultCallbacks?.error(finalMeta.error);\n throw rpcErrors.internal(finalMeta.error.message);\n\n case TransactionStatus.submitted:\n resultCallbacks?.success();\n return finalMeta.hash as string;\n\n default:\n const internalError = rpcErrors.internal(\n `MetaMask Tx Signature: Unknown problem: ${JSON.stringify(\n finalMeta || transactionId,\n )}`,\n );\n\n resultCallbacks?.error(internalError);\n throw internalError;\n }\n }\n\n /**\n * Approves a transaction and updates it's status in state. If this is not a\n * retry transaction, a nonce will be generated. The transaction is signed\n * using the sign configuration property, then published to the blockchain.\n * A `:finished` hub event is fired after success or failure.\n *\n * @param transactionId - The ID of the transaction to approve.\n */\n private async approveTransaction(transactionId: string) {\n const cleanupTasks = new Array<() => void>();\n cleanupTasks.push(await this.mutex.acquire());\n\n let transactionMeta = this.getTransactionOrThrow(transactionId);\n\n try {\n if (!this.sign) {\n this.failTransaction(\n transactionMeta,\n new Error('No sign method defined.'),\n );\n return ApprovalState.NotApproved;\n } else if (!transactionMeta.chainId) {\n this.failTransaction(transactionMeta, new Error('No chainId defined.'));\n return ApprovalState.NotApproved;\n }\n\n if (this.approvingTransactionIds.has(transactionId)) {\n log('Skipping approval as signing in progress', transactionId);\n return ApprovalState.NotApproved;\n }\n this.approvingTransactionIds.add(transactionId);\n cleanupTasks.push(() =>\n this.approvingTransactionIds.delete(transactionId),\n );\n\n const [nonce, releaseNonce] = await getNextNonce(\n transactionMeta,\n (address: string) =>\n this.#multichainTrackingHelper.getNonceLock(\n address,\n transactionMeta.networkClientId,\n ),\n );\n\n // must set transaction to submitted/failed before releasing lock\n releaseNonce && cleanupTasks.push(releaseNonce);\n\n transactionMeta = this.#updateTransactionInternal(\n {\n transactionId,\n note: 'TransactionController#approveTransaction - Transaction approved',\n },\n (draftTxMeta) => {\n const { txParams, chainId } = draftTxMeta;\n\n draftTxMeta.status = TransactionStatus.approved;\n draftTxMeta.txParams = {\n ...txParams,\n nonce,\n chainId,\n gasLimit: txParams.gas,\n ...(isEIP1559Transaction(txParams) && {\n type: TransactionEnvelopeType.feeMarket,\n }),\n };\n },\n );\n\n this.onTransactionStatusChange(transactionMeta);\n\n const rawTx = await this.signTransaction(\n transactionMeta,\n transactionMeta.txParams,\n );\n\n if (!this.beforePublish(transactionMeta)) {\n log('Skipping publishing transaction based on hook');\n this.messagingSystem.publish(\n `${controllerName}:transactionPublishingSkipped`,\n transactionMeta,\n );\n return ApprovalState.SkippedViaBeforePublishHook;\n }\n\n if (!rawTx) {\n return ApprovalState.NotApproved;\n }\n\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId: transactionMeta.networkClientId,\n chainId: transactionMeta.chainId,\n });\n\n let preTxBalance: string | undefined;\n const shouldUpdatePreTxBalance =\n transactionMeta.type === TransactionType.swap;\n\n if (shouldUpdatePreTxBalance) {\n log('Determining pre-transaction balance');\n\n preTxBalance = await query(ethQuery, 'getBalance', [\n transactionMeta.txParams.from,\n ]);\n }\n\n log('Publishing transaction', transactionMeta.txParams);\n\n let { transactionHash: hash } = await this.publish(\n transactionMeta,\n rawTx,\n );\n\n if (hash === undefined) {\n hash = await this.publishTransaction(ethQuery, rawTx);\n }\n\n log('Publish successful', hash);\n\n transactionMeta = this.#updateTransactionInternal(\n {\n transactionId,\n note: 'TransactionController#approveTransaction - Transaction submitted',\n },\n (draftTxMeta) => {\n draftTxMeta.hash = hash;\n draftTxMeta.status = TransactionStatus.submitted;\n draftTxMeta.submittedTime = new Date().getTime();\n if (shouldUpdatePreTxBalance) {\n draftTxMeta.preTxBalance = preTxBalance;\n log('Updated pre-transaction balance', preTxBalance);\n }\n },\n );\n\n this.messagingSystem.publish(`${controllerName}:transactionSubmitted`, {\n transactionMeta,\n });\n\n this.messagingSystem.publish(\n `${controllerName}:transactionFinished`,\n transactionMeta,\n );\n this.#internalEvents.emit(`${transactionId}:finished`, transactionMeta);\n\n this.onTransactionStatusChange(transactionMeta);\n return ApprovalState.Approved;\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (error: any) {\n this.failTransaction(transactionMeta, error);\n return ApprovalState.NotApproved;\n } finally {\n cleanupTasks.forEach((task) => task());\n }\n }\n\n private async publishTransaction(\n ethQuery: EthQuery,\n rawTransaction: string,\n ): Promise {\n return await query(ethQuery, 'sendRawTransaction', [rawTransaction]);\n }\n\n /**\n * Cancels a transaction based on its ID by setting its status to \"rejected\"\n * and emitting a `:finished` hub event.\n *\n * @param transactionId - The ID of the transaction to cancel.\n * @param actionId - The actionId passed from UI\n */\n private cancelTransaction(transactionId: string, actionId?: string) {\n const transactionMeta = this.state.transactions.find(\n ({ id }) => id === transactionId,\n );\n if (!transactionMeta) {\n return;\n }\n this.update((state) => {\n const transactions = state.transactions.filter(\n ({ id }) => id !== transactionId,\n );\n state.transactions = this.trimTransactionsForState(transactions);\n });\n const updatedTransactionMeta = {\n ...transactionMeta,\n status: TransactionStatus.rejected as const,\n };\n this.messagingSystem.publish(\n `${controllerName}:transactionFinished`,\n updatedTransactionMeta,\n );\n this.#internalEvents.emit(\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n `${transactionMeta.id}:finished`,\n updatedTransactionMeta,\n );\n this.messagingSystem.publish(`${controllerName}:transactionRejected`, {\n transactionMeta: updatedTransactionMeta,\n actionId,\n });\n this.onTransactionStatusChange(updatedTransactionMeta);\n }\n\n /**\n * Trim the amount of transactions that are set on the state. Checks\n * if the length of the tx history is longer then desired persistence\n * limit and then if it is removes the oldest confirmed or rejected tx.\n * Pending or unapproved transactions will not be removed by this\n * operation. For safety of presenting a fully functional transaction UI\n * representation, this function will not break apart transactions with the\n * same nonce, created on the same day, per network. Not accounting for\n * transactions of the same nonce, same day and network combo can result in\n * confusing or broken experiences in the UI.\n *\n * @param transactions - The transactions to be applied to the state.\n * @returns The trimmed list of transactions.\n */\n private trimTransactionsForState(\n transactions: TransactionMeta[],\n ): TransactionMeta[] {\n const nonceNetworkSet = new Set();\n\n const txsToKeep = [...transactions]\n .sort((a, b) => (a.time > b.time ? -1 : 1)) // Descending time order\n .filter((tx) => {\n const { chainId, status, txParams, time } = tx;\n\n if (txParams) {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n const key = `${String(txParams.nonce)}-${convertHexToDecimal(\n chainId,\n )}-${new Date(time).toDateString()}`;\n\n if (nonceNetworkSet.has(key)) {\n return true;\n } else if (\n nonceNetworkSet.size < this.#transactionHistoryLimit ||\n !this.isFinalState(status)\n ) {\n nonceNetworkSet.add(key);\n return true;\n }\n }\n\n return false;\n });\n\n txsToKeep.reverse(); // Ascending time order\n return txsToKeep;\n }\n\n /**\n * Determines if the transaction is in a final state.\n *\n * @param status - The transaction status.\n * @returns Whether the transaction is in a final state.\n */\n private isFinalState(status: TransactionStatus): boolean {\n return (\n status === TransactionStatus.rejected ||\n status === TransactionStatus.confirmed ||\n status === TransactionStatus.failed\n );\n }\n\n /**\n * Whether the transaction has at least completed all local processing.\n *\n * @param status - The transaction status.\n * @returns Whether the transaction is in a final state.\n */\n private isLocalFinalState(status: TransactionStatus): boolean {\n return [\n TransactionStatus.confirmed,\n TransactionStatus.failed,\n TransactionStatus.rejected,\n TransactionStatus.submitted,\n ].includes(status);\n }\n\n private async requestApproval(\n txMeta: TransactionMeta,\n { shouldShowRequest }: { shouldShowRequest: boolean },\n ): Promise {\n const id = this.getApprovalId(txMeta);\n const { origin } = txMeta;\n const type = ApprovalType.Transaction;\n const requestData = { txId: txMeta.id };\n\n return (await this.messagingSystem.call(\n 'ApprovalController:addRequest',\n {\n id,\n origin: origin || ORIGIN_METAMASK,\n type,\n requestData,\n expectsResult: true,\n },\n shouldShowRequest,\n )) as Promise;\n }\n\n private getTransaction(\n transactionId: string,\n ): Readonly | undefined {\n const { transactions } = this.state;\n return transactions.find(({ id }) => id === transactionId);\n }\n\n private getTransactionOrThrow(\n transactionId: string,\n errorMessagePrefix = 'TransactionController',\n ): Readonly {\n const txMeta = this.getTransaction(transactionId);\n if (!txMeta) {\n throw new Error(\n `${errorMessagePrefix}: No transaction found with id ${transactionId}`,\n );\n }\n return txMeta;\n }\n\n private getApprovalId(txMeta: TransactionMeta) {\n return String(txMeta.id);\n }\n\n private isTransactionCompleted(transactionId: string): {\n meta?: TransactionMeta;\n isCompleted: boolean;\n } {\n const transaction = this.getTransaction(transactionId);\n\n if (!transaction) {\n return { meta: undefined, isCompleted: false };\n }\n\n const isCompleted = this.isLocalFinalState(transaction.status);\n\n return { meta: transaction, isCompleted };\n }\n\n private getChainId(networkClientId?: NetworkClientId): Hex {\n const globalChainId = this.#getGlobalChainId();\n const globalNetworkClientId = this.#getGlobalNetworkClientId();\n\n if (!networkClientId || networkClientId === globalNetworkClientId) {\n return globalChainId;\n }\n\n return this.messagingSystem.call(\n `NetworkController:getNetworkClientById`,\n networkClientId,\n ).configuration.chainId;\n }\n\n private prepareUnsignedEthTx(\n chainId: Hex,\n txParams: TransactionParams,\n ): TypedTransaction {\n return TransactionFactory.fromTxData(txParams, {\n freeze: false,\n common: this.getCommonConfiguration(chainId),\n });\n }\n\n /**\n * `@ethereumjs/tx` uses `@ethereumjs/common` as a configuration tool for\n * specifying which chain, network, hardfork and EIPs to support for\n * a transaction. By referencing this configuration, and analyzing the fields\n * specified in txParams, @ethereumjs/tx is able to determine which EIP-2718\n * transaction type to use.\n *\n * @param chainId - The chainId to use for the configuration.\n * @returns common configuration object\n */\n private getCommonConfiguration(chainId: Hex): Common {\n const customChainParams: Partial = {\n chainId: parseInt(chainId, 16),\n defaultHardfork: HARDFORK,\n };\n\n return Common.custom(customChainParams);\n }\n\n private onIncomingTransactions({\n added,\n updated,\n }: {\n added: TransactionMeta[];\n updated: TransactionMeta[];\n }) {\n this.update((state) => {\n const { transactions: currentTransactions } = state;\n const updatedTransactions = [\n ...added,\n ...currentTransactions.map((originalTransaction) => {\n const updatedTransaction = updated.find(\n ({ hash }) => hash === originalTransaction.hash,\n );\n\n return updatedTransaction ?? originalTransaction;\n }),\n ];\n\n state.transactions = this.trimTransactionsForState(updatedTransactions);\n });\n }\n\n private onUpdatedLastFetchedBlockNumbers({\n lastFetchedBlockNumbers,\n blockNumber,\n }: {\n lastFetchedBlockNumbers: {\n [key: string]: number;\n };\n blockNumber: number;\n }) {\n this.update((state) => {\n state.lastFetchedBlockNumbers = lastFetchedBlockNumbers;\n });\n this.messagingSystem.publish(\n `${controllerName}:incomingTransactionBlockReceived`,\n blockNumber,\n );\n }\n\n private generateDappSuggestedGasFees(\n txParams: TransactionParams,\n origin?: string,\n ): DappSuggestedGasFees | undefined {\n if (!origin || origin === ORIGIN_METAMASK) {\n return undefined;\n }\n\n const { gasPrice, maxFeePerGas, maxPriorityFeePerGas, gas } = txParams;\n\n if (\n gasPrice === undefined &&\n maxFeePerGas === undefined &&\n maxPriorityFeePerGas === undefined &&\n gas === undefined\n ) {\n return undefined;\n }\n\n const dappSuggestedGasFees: DappSuggestedGasFees = {};\n\n if (gasPrice !== undefined) {\n dappSuggestedGasFees.gasPrice = gasPrice;\n } else if (\n maxFeePerGas !== undefined ||\n maxPriorityFeePerGas !== undefined\n ) {\n dappSuggestedGasFees.maxFeePerGas = maxFeePerGas;\n dappSuggestedGasFees.maxPriorityFeePerGas = maxPriorityFeePerGas;\n }\n\n if (gas !== undefined) {\n dappSuggestedGasFees.gas = gas;\n }\n\n return dappSuggestedGasFees;\n }\n\n /**\n * Validates and adds external provided transaction to state.\n *\n * @param transactionMeta - Nominated external transaction to be added to state.\n * @returns The new transaction.\n */\n private addExternalTransaction(transactionMeta: TransactionMeta) {\n const { chainId } = transactionMeta;\n const { transactions } = this.state;\n const fromAddress = transactionMeta?.txParams?.from;\n const sameFromAndNetworkTransactions = transactions.filter(\n (transaction) =>\n transaction.txParams.from === fromAddress &&\n transaction.chainId === chainId,\n );\n const confirmedTxs = sameFromAndNetworkTransactions.filter(\n (transaction) => transaction.status === TransactionStatus.confirmed,\n );\n const pendingTxs = sameFromAndNetworkTransactions.filter(\n (transaction) => transaction.status === TransactionStatus.submitted,\n );\n\n validateConfirmedExternalTransaction(\n transactionMeta,\n confirmedTxs,\n pendingTxs,\n );\n\n // Make sure provided external transaction has non empty history array\n const newTransactionMeta =\n (transactionMeta.history ?? []).length === 0 && !this.isHistoryDisabled\n ? addInitialHistorySnapshot(transactionMeta)\n : transactionMeta;\n\n this.update((state) => {\n state.transactions = this.trimTransactionsForState([\n ...state.transactions,\n newTransactionMeta,\n ]);\n });\n\n return newTransactionMeta;\n }\n\n /**\n * Sets other txMeta statuses to dropped if the txMeta that has been confirmed has other transactions\n * in the transactions have the same nonce.\n *\n * @param transactionId - Used to identify original transaction.\n */\n private markNonceDuplicatesDropped(transactionId: string) {\n const transactionMeta = this.getTransaction(transactionId);\n if (!transactionMeta) {\n return;\n }\n const nonce = transactionMeta.txParams?.nonce;\n const from = transactionMeta.txParams?.from;\n const { chainId } = transactionMeta;\n\n const sameNonceTransactions = this.state.transactions.filter(\n (transaction) =>\n transaction.id !== transactionId &&\n transaction.txParams.from === from &&\n transaction.txParams.nonce === nonce &&\n transaction.chainId === chainId &&\n transaction.type !== TransactionType.incoming,\n );\n const sameNonceTransactionIds = sameNonceTransactions.map(\n (transaction) => transaction.id,\n );\n\n if (sameNonceTransactions.length === 0) {\n return;\n }\n\n this.update((state) => {\n for (const transaction of state.transactions) {\n if (sameNonceTransactionIds.includes(transaction.id)) {\n transaction.replacedBy = transactionMeta?.hash;\n transaction.replacedById = transactionMeta?.id;\n }\n }\n });\n\n for (const transaction of this.state.transactions) {\n if (\n sameNonceTransactionIds.includes(transaction.id) &&\n transaction.status !== TransactionStatus.failed\n ) {\n this.setTransactionStatusDropped(transaction);\n }\n }\n }\n\n /**\n * Method to set transaction status to dropped.\n *\n * @param transactionMeta - TransactionMeta of transaction to be marked as dropped.\n */\n private setTransactionStatusDropped(transactionMeta: TransactionMeta) {\n const updatedTransactionMeta = {\n ...transactionMeta,\n status: TransactionStatus.dropped as const,\n };\n this.messagingSystem.publish(`${controllerName}:transactionDropped`, {\n transactionMeta: updatedTransactionMeta,\n });\n this.updateTransaction(\n updatedTransactionMeta,\n 'TransactionController#setTransactionStatusDropped - Transaction dropped',\n );\n this.onTransactionStatusChange(updatedTransactionMeta);\n }\n\n /**\n * Get transaction with provided actionId.\n *\n * @param actionId - Unique ID to prevent duplicate requests\n * @returns the filtered transaction\n */\n private getTransactionWithActionId(actionId?: string) {\n return this.state.transactions.find(\n (transaction) => actionId && transaction.actionId === actionId,\n );\n }\n\n private async waitForTransactionFinished(\n transactionId: string,\n ): Promise {\n return new Promise((resolve) => {\n this.#internalEvents.once(`${transactionId}:finished`, (txMeta) => {\n resolve(txMeta);\n });\n });\n }\n\n /**\n * Updates the r, s, and v properties of a TransactionMeta object\n * with values from a signed transaction.\n *\n * @param transactionMeta - The TransactionMeta object to update.\n * @param signedTx - The encompassing type for all transaction types containing r, s, and v values.\n * @returns The updated TransactionMeta object.\n */\n private updateTransactionMetaRSV(\n transactionMeta: TransactionMeta,\n signedTx: TypedTransaction,\n ): TransactionMeta {\n const transactionMetaWithRsv = cloneDeep(transactionMeta);\n\n for (const key of ['r', 's', 'v'] as const) {\n const value = signedTx[key];\n\n if (value === undefined || value === null) {\n continue;\n }\n\n transactionMetaWithRsv[key] = add0x(value.toString(16));\n }\n\n return transactionMetaWithRsv;\n }\n\n private async getEIP1559Compatibility(networkClientId?: NetworkClientId) {\n const currentNetworkIsEIP1559Compatible =\n await this.getCurrentNetworkEIP1559Compatibility(networkClientId);\n\n const currentAccountIsEIP1559Compatible =\n await this.getCurrentAccountEIP1559Compatibility();\n\n return (\n currentNetworkIsEIP1559Compatible && currentAccountIsEIP1559Compatible\n );\n }\n\n private async signTransaction(\n transactionMeta: TransactionMeta,\n txParams: TransactionParams,\n ): Promise {\n log('Signing transaction', txParams);\n\n const unsignedEthTx = this.prepareUnsignedEthTx(\n transactionMeta.chainId,\n txParams,\n );\n\n this.approvingTransactionIds.add(transactionMeta.id);\n\n const signedTx = await new Promise((resolve, reject) => {\n this.sign?.(\n unsignedEthTx,\n txParams.from,\n ...this.getAdditionalSignArguments(transactionMeta),\n ).then(resolve, reject);\n\n this.signAbortCallbacks.set(transactionMeta.id, () =>\n reject(new Error('Signing aborted by user')),\n );\n });\n\n this.signAbortCallbacks.delete(transactionMeta.id);\n\n if (!signedTx) {\n log('Skipping signed status as no signed transaction');\n return undefined;\n }\n\n const transactionMetaFromHook = cloneDeep(transactionMeta);\n if (!this.afterSign(transactionMetaFromHook, signedTx)) {\n this.updateTransaction(\n transactionMetaFromHook,\n 'TransactionController#signTransaction - Update after sign',\n );\n\n log('Skipping signed status based on hook');\n\n return undefined;\n }\n\n const transactionMetaWithRsv = {\n ...this.updateTransactionMetaRSV(transactionMetaFromHook, signedTx),\n status: TransactionStatus.signed as const,\n };\n\n this.updateTransaction(\n transactionMetaWithRsv,\n 'TransactionController#approveTransaction - Transaction signed',\n );\n\n this.onTransactionStatusChange(transactionMetaWithRsv);\n\n const rawTx = bufferToHex(signedTx.serialize());\n\n const transactionMetaWithRawTx = merge({}, transactionMetaWithRsv, {\n rawTx,\n });\n\n this.updateTransaction(\n transactionMetaWithRawTx,\n 'TransactionController#approveTransaction - RawTransaction added',\n );\n\n return rawTx;\n }\n\n private onTransactionStatusChange(transactionMeta: TransactionMeta) {\n this.messagingSystem.publish(`${controllerName}:transactionStatusUpdated`, {\n transactionMeta,\n });\n }\n\n private getNonceTrackerTransactions(\n status: TransactionStatus,\n address: string,\n chainId: string = this.getChainId(),\n ) {\n return getAndFormatTransactionsForNonceTracker(\n chainId,\n address,\n status,\n this.state.transactions,\n );\n }\n\n private onConfirmedTransaction(transactionMeta: TransactionMeta) {\n log('Processing confirmed transaction', transactionMeta.id);\n\n this.markNonceDuplicatesDropped(transactionMeta.id);\n\n this.messagingSystem.publish(\n `${controllerName}:transactionConfirmed`,\n transactionMeta,\n );\n\n this.onTransactionStatusChange(transactionMeta);\n\n // Intentional given potential duration of process.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.updatePostBalance(transactionMeta);\n }\n\n private async updatePostBalance(transactionMeta: TransactionMeta) {\n try {\n if (transactionMeta.type !== TransactionType.swap) {\n return;\n }\n\n const ethQuery = this.#multichainTrackingHelper.getEthQuery({\n networkClientId: transactionMeta.networkClientId,\n chainId: transactionMeta.chainId,\n });\n const { updatedTransactionMeta, approvalTransactionMeta } =\n await updatePostTransactionBalance(transactionMeta, {\n ethQuery,\n getTransaction: this.getTransaction.bind(this),\n updateTransaction: this.updateTransaction.bind(this),\n });\n\n this.messagingSystem.publish(\n `${controllerName}:postTransactionBalanceUpdated`,\n {\n transactionMeta: updatedTransactionMeta,\n approvalTransactionMeta,\n },\n );\n } catch (error) {\n /* istanbul ignore next */\n log('Error while updating post transaction balance', error);\n }\n }\n\n #createNonceTracker({\n provider,\n blockTracker,\n chainId,\n }: {\n provider: Provider;\n blockTracker: BlockTracker;\n chainId?: Hex;\n }): NonceTracker {\n return new NonceTracker({\n // TODO: Fix types\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n provider: provider as any,\n // @ts-expect-error TODO: Fix types\n blockTracker,\n getPendingTransactions: this.#getNonceTrackerPendingTransactions.bind(\n this,\n chainId,\n ),\n getConfirmedTransactions: this.getNonceTrackerTransactions.bind(\n this,\n TransactionStatus.confirmed,\n ),\n });\n }\n\n #createIncomingTransactionHelper({\n blockTracker,\n etherscanRemoteTransactionSource,\n chainId,\n }: {\n blockTracker: BlockTracker;\n etherscanRemoteTransactionSource: EtherscanRemoteTransactionSource;\n chainId?: Hex;\n }): IncomingTransactionHelper {\n const incomingTransactionHelper = new IncomingTransactionHelper({\n blockTracker,\n getCurrentAccount: () => this.#getSelectedAccount(),\n getLastFetchedBlockNumbers: () => this.state.lastFetchedBlockNumbers,\n getChainId: chainId ? () => chainId : this.getChainId.bind(this),\n isEnabled: this.#incomingTransactionOptions.isEnabled,\n queryEntireHistory: this.#incomingTransactionOptions.queryEntireHistory,\n remoteTransactionSource: etherscanRemoteTransactionSource,\n transactionLimit: this.#transactionHistoryLimit,\n updateTransactions: this.#incomingTransactionOptions.updateTransactions,\n });\n\n this.#addIncomingTransactionHelperListeners(incomingTransactionHelper);\n\n return incomingTransactionHelper;\n }\n\n #createPendingTransactionTracker({\n provider,\n blockTracker,\n chainId,\n }: {\n provider: Provider;\n blockTracker: BlockTracker;\n chainId?: Hex;\n }): PendingTransactionTracker {\n const ethQuery = new EthQuery(provider);\n const getChainId = chainId ? () => chainId : this.getChainId.bind(this);\n\n const pendingTransactionTracker = new PendingTransactionTracker({\n blockTracker,\n getChainId,\n getEthQuery: () => ethQuery,\n getTransactions: () => this.state.transactions,\n isResubmitEnabled: this.#pendingTransactionOptions.isResubmitEnabled,\n getGlobalLock: () =>\n this.#multichainTrackingHelper.acquireNonceLockForChainIdKey({\n chainId: getChainId(),\n }),\n publishTransaction: this.publishTransaction.bind(this),\n hooks: {\n beforeCheckPendingTransaction:\n this.beforeCheckPendingTransaction.bind(this),\n beforePublish: this.beforePublish.bind(this),\n },\n });\n\n this.#addPendingTransactionTrackerListeners(pendingTransactionTracker);\n\n return pendingTransactionTracker;\n }\n\n #checkForPendingTransactionAndStartPolling = () => {\n // PendingTransactionTracker reads state through its getTransactions hook\n this.pendingTransactionTracker.startIfPendingTransactions();\n this.#multichainTrackingHelper.checkForPendingTransactionAndStartPolling();\n };\n\n #stopAllTracking() {\n this.pendingTransactionTracker.stop();\n this.#removePendingTransactionTrackerListeners(\n this.pendingTransactionTracker,\n );\n this.incomingTransactionHelper.stop();\n this.#removeIncomingTransactionHelperListeners(\n this.incomingTransactionHelper,\n );\n\n this.#multichainTrackingHelper.stopAllTracking();\n }\n\n #removeIncomingTransactionHelperListeners(\n incomingTransactionHelper: IncomingTransactionHelper,\n ) {\n incomingTransactionHelper.hub.removeAllListeners('transactions');\n incomingTransactionHelper.hub.removeAllListeners(\n 'updatedLastFetchedBlockNumbers',\n );\n }\n\n #addIncomingTransactionHelperListeners(\n incomingTransactionHelper: IncomingTransactionHelper,\n ) {\n incomingTransactionHelper.hub.on(\n 'transactions',\n this.onIncomingTransactions.bind(this),\n );\n incomingTransactionHelper.hub.on(\n 'updatedLastFetchedBlockNumbers',\n this.onUpdatedLastFetchedBlockNumbers.bind(this),\n );\n }\n\n #removePendingTransactionTrackerListeners(\n pendingTransactionTracker: PendingTransactionTracker,\n ) {\n pendingTransactionTracker.hub.removeAllListeners('transaction-confirmed');\n pendingTransactionTracker.hub.removeAllListeners('transaction-dropped');\n pendingTransactionTracker.hub.removeAllListeners('transaction-failed');\n pendingTransactionTracker.hub.removeAllListeners('transaction-updated');\n }\n\n #addPendingTransactionTrackerListeners(\n pendingTransactionTracker: PendingTransactionTracker,\n ) {\n pendingTransactionTracker.hub.on(\n 'transaction-confirmed',\n this.onConfirmedTransaction.bind(this),\n );\n\n pendingTransactionTracker.hub.on(\n 'transaction-dropped',\n this.setTransactionStatusDropped.bind(this),\n );\n\n pendingTransactionTracker.hub.on(\n 'transaction-failed',\n this.failTransaction.bind(this),\n );\n\n pendingTransactionTracker.hub.on(\n 'transaction-updated',\n this.updateTransaction.bind(this),\n );\n }\n\n #getNonceTrackerPendingTransactions(\n chainId: string | undefined,\n address: string,\n ) {\n const standardPendingTransactions = this.getNonceTrackerTransactions(\n TransactionStatus.submitted,\n address,\n chainId,\n );\n\n const externalPendingTransactions = this.getExternalPendingTransactions(\n address,\n chainId,\n );\n return [...standardPendingTransactions, ...externalPendingTransactions];\n }\n\n private async publishTransactionForRetry(\n ethQuery: EthQuery,\n rawTx: string,\n transactionMeta: TransactionMeta,\n ): Promise {\n try {\n const hash = await this.publishTransaction(ethQuery, rawTx);\n return hash;\n } catch (error: unknown) {\n if (this.isTransactionAlreadyConfirmedError(error as Error)) {\n await this.pendingTransactionTracker.forceCheckTransaction(\n transactionMeta,\n );\n throw new Error('Previous transaction is already confirmed');\n }\n throw error;\n }\n }\n\n /**\n * Ensures that error is a nonce issue\n *\n * @param error - The error to check\n * @returns Whether or not the error is a nonce issue\n */\n // TODO: Replace `any` with type\n // Some networks are returning original error in the data field\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private isTransactionAlreadyConfirmedError(error: any): boolean {\n return (\n error?.message?.includes('nonce too low') ||\n error?.data?.message?.includes('nonce too low')\n );\n }\n\n #getGasFeeFlows(): GasFeeFlow[] {\n if (this.#testGasFeeFlows) {\n return [new TestGasFeeFlow()];\n }\n\n return [new LineaGasFeeFlow(), new DefaultGasFeeFlow()];\n }\n\n #getLayer1GasFeeFlows(): Layer1GasFeeFlow[] {\n return [new OptimismLayer1GasFeeFlow(), new ScrollLayer1GasFeeFlow()];\n }\n\n #updateTransactionInternal(\n {\n transactionId,\n note,\n skipHistory,\n skipValidation,\n }: {\n transactionId: string;\n note?: string;\n skipHistory?: boolean;\n skipValidation?: boolean;\n },\n callback: (transactionMeta: TransactionMeta) => TransactionMeta | void,\n ): Readonly {\n let updatedTransactionParams: (keyof TransactionParams)[] = [];\n\n this.update((state) => {\n const index = state.transactions.findIndex(\n ({ id }) => id === transactionId,\n );\n\n let transactionMeta = state.transactions[index];\n\n // eslint-disable-next-line n/callback-return\n transactionMeta = callback(transactionMeta) ?? transactionMeta;\n\n if (skipValidation !== true) {\n transactionMeta.txParams = normalizeTransactionParams(\n transactionMeta.txParams,\n );\n\n validateTxParams(transactionMeta.txParams);\n }\n\n updatedTransactionParams =\n this.#checkIfTransactionParamsUpdated(transactionMeta);\n\n const shouldSkipHistory = this.isHistoryDisabled || skipHistory;\n\n if (!shouldSkipHistory) {\n transactionMeta = updateTransactionHistory(\n transactionMeta,\n note ?? 'Transaction updated',\n );\n }\n state.transactions[index] = transactionMeta;\n });\n\n const transactionMeta = this.getTransaction(\n transactionId,\n ) as TransactionMeta;\n\n if (updatedTransactionParams.length > 0) {\n this.#onTransactionParamsUpdated(\n transactionMeta,\n updatedTransactionParams,\n );\n }\n\n return transactionMeta;\n }\n\n #checkIfTransactionParamsUpdated(newTransactionMeta: TransactionMeta) {\n const { id: transactionId, txParams: newParams } = newTransactionMeta;\n\n const originalParams = this.getTransaction(transactionId)?.txParams;\n\n if (!originalParams || isEqual(originalParams, newParams)) {\n return [];\n }\n\n const params = Object.keys(newParams) as (keyof TransactionParams)[];\n\n const updatedProperties = params.filter(\n (param) => newParams[param] !== originalParams[param],\n );\n\n log(\n 'Transaction parameters have been updated',\n transactionId,\n updatedProperties,\n originalParams,\n newParams,\n );\n\n return updatedProperties;\n }\n\n #onTransactionParamsUpdated(\n transactionMeta: TransactionMeta,\n updatedParams: (keyof TransactionParams)[],\n ) {\n if (\n (['to', 'value', 'data'] as const).some((param) =>\n updatedParams.includes(param),\n )\n ) {\n log('Updating simulation data due to transaction parameter update');\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.#updateSimulationData(transactionMeta);\n }\n }\n\n async #updateSimulationData(transactionMeta: TransactionMeta) {\n const { id: transactionId, chainId, txParams } = transactionMeta;\n const { from, to, value, data } = txParams;\n\n let simulationData: SimulationData = {\n error: {\n code: SimulationErrorCode.Disabled,\n message: 'Simulation disabled',\n },\n tokenBalanceChanges: [],\n };\n\n if (this.#isSimulationEnabled()) {\n this.#updateTransactionInternal(\n { transactionId, skipHistory: true },\n (txMeta) => {\n txMeta.simulationData = undefined;\n },\n );\n\n simulationData = await getSimulationData({\n chainId,\n from: from as Hex,\n to: to as Hex,\n value: value as Hex,\n data: data as Hex,\n });\n }\n\n const finalTransactionMeta = this.getTransaction(transactionId);\n\n /* istanbul ignore if */\n if (!finalTransactionMeta) {\n log(\n 'Cannot update simulation data as transaction not found',\n transactionId,\n simulationData,\n );\n\n return;\n }\n\n this.#updateTransactionInternal(\n {\n transactionId,\n note: 'TransactionController#updateSimulationData - Update simulation data',\n },\n (txMeta) => {\n txMeta.simulationData = simulationData;\n },\n );\n\n log('Updated simulation data', transactionId, simulationData);\n }\n\n #onGasFeePollerTransactionUpdate({\n transactionId,\n gasFeeEstimates,\n gasFeeEstimatesLoaded,\n layer1GasFee,\n }: {\n transactionId: string;\n gasFeeEstimates?: GasFeeEstimates;\n gasFeeEstimatesLoaded?: boolean;\n layer1GasFee?: Hex;\n }) {\n this.#updateTransactionInternal(\n { transactionId, skipHistory: true },\n (txMeta) => {\n if (gasFeeEstimates) {\n txMeta.gasFeeEstimates = gasFeeEstimates;\n }\n\n if (gasFeeEstimatesLoaded !== undefined) {\n txMeta.gasFeeEstimatesLoaded = gasFeeEstimatesLoaded;\n }\n\n if (layer1GasFee) {\n txMeta.layer1GasFee = layer1GasFee;\n }\n },\n );\n }\n\n #getNetworkClientId({\n networkClientId: requestNetworkClientId,\n chainId,\n }: {\n networkClientId?: NetworkClientId;\n chainId?: Hex;\n }) {\n const globalChainId = this.#getGlobalChainId();\n const globalNetworkClientId = this.#getGlobalNetworkClientId();\n\n if (requestNetworkClientId) {\n return requestNetworkClientId;\n }\n\n if (!chainId || chainId === globalChainId) {\n return globalNetworkClientId;\n }\n\n return this.messagingSystem.call(\n `NetworkController:findNetworkClientIdByChainId`,\n chainId,\n );\n }\n\n #getGlobalNetworkClientId() {\n return this.getNetworkState().selectedNetworkClientId;\n }\n\n #getGlobalChainId() {\n return this.messagingSystem.call(\n `NetworkController:getNetworkClientById`,\n this.getNetworkState().selectedNetworkClientId,\n ).configuration.chainId;\n }\n\n #isCustomNetwork(networkClientId?: NetworkClientId) {\n const globalNetworkClientId = this.#getGlobalNetworkClientId();\n\n if (!networkClientId || networkClientId === globalNetworkClientId) {\n return !isInfuraNetworkType(\n this.getNetworkState().selectedNetworkClientId,\n );\n }\n\n return (\n this.messagingSystem.call(\n `NetworkController:getNetworkClientById`,\n networkClientId,\n ).configuration.type === NetworkClientType.Custom\n );\n }\n\n #getSelectedAccount() {\n return this.messagingSystem.call('AccountsController:getSelectedAccount');\n }\n}\n"],"mappings":"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","names":["ApprovalState","transactionMeta"]}
+\ No newline at end of file
+diff --git a/dist/helpers/PendingTransactionTracker.js b/dist/helpers/PendingTransactionTracker.js
+index 339a7782f047161c1909f8a91bb4299fad55a5f0..fb40ba14596eb229b004073776cfe1ddb171094a 100644
+--- a/dist/helpers/PendingTransactionTracker.js
++++ b/dist/helpers/PendingTransactionTracker.js
+@@ -1,10 +1,10 @@
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
+
+-var _chunkULD4JC3Qjs = require('../chunk-ULD4JC3Q.js');
++var _chunk6DODV6OVjs = require('../chunk-6DODV6OV.js');
+ require('../chunk-S6VGOPUY.js');
+ require('../chunk-AYTU4HU5.js');
+ require('../chunk-Z4BLTVTB.js');
+
+
+-exports.PendingTransactionTracker = _chunkULD4JC3Qjs.PendingTransactionTracker;
++exports.PendingTransactionTracker = _chunk6DODV6OVjs.PendingTransactionTracker;
+ //# sourceMappingURL=PendingTransactionTracker.js.map
+\ No newline at end of file
+diff --git a/dist/helpers/PendingTransactionTracker.mjs b/dist/helpers/PendingTransactionTracker.mjs
+index e942405e82ab16407d8cbf318d84c1991f4e20d4..546ccbc8aede4f95bccc47d7c495000a8128dd82 100644
+--- a/dist/helpers/PendingTransactionTracker.mjs
++++ b/dist/helpers/PendingTransactionTracker.mjs
+@@ -1,6 +1,6 @@
+ import {
+ PendingTransactionTracker
+-} from "../chunk-6B5BEO3R.mjs";
++} from "../chunk-7M2R5AHC.mjs";
+ import "../chunk-UQQWZT6C.mjs";
+ import "../chunk-6SJYXSF3.mjs";
+ import "../chunk-XUI43LEZ.mjs";
+diff --git a/dist/index.js b/dist/index.js
+index 16f7e96ba4efe3f7d7aec6cecbb1fce6f991dd0b..77e7c5cc78efe603bcd6afbe95a5a6dee9cae719 100644
+--- a/dist/index.js
++++ b/dist/index.js
+@@ -2,7 +2,7 @@
+
+
+
+-var _chunkS7Q622ISjs = require('./chunk-S7Q622IS.js');
++var _chunkIVR4NMOFjs = require('./chunk-IVR4NMOF.js');
+ require('./chunk-PRUNMTRD.js');
+ require('./chunk-74W7X6BE.js');
+ require('./chunk-KT6UAKBB.js');
+@@ -10,7 +10,7 @@ require('./chunk-KT6UAKBB.js');
+
+ var _chunkSD6CWFDFjs = require('./chunk-SD6CWFDF.js');
+ require('./chunk-RXIUMVA5.js');
+-require('./chunk-ULD4JC3Q.js');
++require('./chunk-6DODV6OV.js');
+ require('./chunk-7LXE4KHV.js');
+ require('./chunk-V72C4MCR.js');
+ require('./chunk-QP75SWIQ.js');
+@@ -67,5 +67,5 @@ require('./chunk-Z4BLTVTB.js');
+
+
+
+-exports.CANCEL_RATE = _chunkS7Q622ISjs.CANCEL_RATE; exports.GasFeeEstimateLevel = _chunkAYTU4HU5js.GasFeeEstimateLevel; exports.GasFeeEstimateType = _chunkAYTU4HU5js.GasFeeEstimateType; exports.HARDFORK = _chunkS7Q622ISjs.HARDFORK; exports.SimulationErrorCode = _chunkAYTU4HU5js.SimulationErrorCode; exports.SimulationTokenStandard = _chunkAYTU4HU5js.SimulationTokenStandard; exports.TransactionController = _chunkS7Q622ISjs.TransactionController; exports.TransactionEnvelopeType = _chunkAYTU4HU5js.TransactionEnvelopeType; exports.TransactionStatus = _chunkAYTU4HU5js.TransactionStatus; exports.TransactionType = _chunkAYTU4HU5js.TransactionType; exports.UserFeeLevel = _chunkAYTU4HU5js.UserFeeLevel; exports.WalletDevice = _chunkAYTU4HU5js.WalletDevice; exports.determineTransactionType = _chunkSD6CWFDFjs.determineTransactionType; exports.isEIP1559Transaction = _chunkOZ6UB42Cjs.isEIP1559Transaction; exports.mergeGasFeeEstimates = _chunk76FONEDAjs.mergeGasFeeEstimates; exports.normalizeTransactionParams = _chunkOZ6UB42Cjs.normalizeTransactionParams;
++exports.CANCEL_RATE = _chunkIVR4NMOFjs.CANCEL_RATE; exports.GasFeeEstimateLevel = _chunkAYTU4HU5js.GasFeeEstimateLevel; exports.GasFeeEstimateType = _chunkAYTU4HU5js.GasFeeEstimateType; exports.HARDFORK = _chunkIVR4NMOFjs.HARDFORK; exports.SimulationErrorCode = _chunkAYTU4HU5js.SimulationErrorCode; exports.SimulationTokenStandard = _chunkAYTU4HU5js.SimulationTokenStandard; exports.TransactionController = _chunkIVR4NMOFjs.TransactionController; exports.TransactionEnvelopeType = _chunkAYTU4HU5js.TransactionEnvelopeType; exports.TransactionStatus = _chunkAYTU4HU5js.TransactionStatus; exports.TransactionType = _chunkAYTU4HU5js.TransactionType; exports.UserFeeLevel = _chunkAYTU4HU5js.UserFeeLevel; exports.WalletDevice = _chunkAYTU4HU5js.WalletDevice; exports.determineTransactionType = _chunkSD6CWFDFjs.determineTransactionType; exports.isEIP1559Transaction = _chunkOZ6UB42Cjs.isEIP1559Transaction; exports.mergeGasFeeEstimates = _chunk76FONEDAjs.mergeGasFeeEstimates; exports.normalizeTransactionParams = _chunkOZ6UB42Cjs.normalizeTransactionParams;
+ //# sourceMappingURL=index.js.map
+\ No newline at end of file
+diff --git a/dist/index.mjs b/dist/index.mjs
+index edca04b36c84ba0245f49301275dbc5d49edeb18..a3506a7fa4f3050ff689540eefcddadd5d934b6b 100644
+--- a/dist/index.mjs
++++ b/dist/index.mjs
+@@ -2,7 +2,7 @@ import {
+ CANCEL_RATE,
+ HARDFORK,
+ TransactionController
+-} from "./chunk-UKV5HIMT.mjs";
++} from "./chunk-YQYO6EGF.mjs";
+ import "./chunk-6DDVVUJC.mjs";
+ import "./chunk-EVL6KODQ.mjs";
+ import "./chunk-K4KOSAGM.mjs";
+@@ -10,7 +10,7 @@ import {
+ determineTransactionType
+ } from "./chunk-KG4UW4K4.mjs";
+ import "./chunk-5ZEJT5SN.mjs";
+-import "./chunk-6B5BEO3R.mjs";
++import "./chunk-7M2R5AHC.mjs";
+ import "./chunk-FRKQ3Z2L.mjs";
+ import "./chunk-5G6OHAXI.mjs";
+ import "./chunk-XGRAHX6T.mjs";
+diff --git a/dist/tsconfig.build.tsbuildinfo b/dist/tsconfig.build.tsbuildinfo
+index 32138a8b41ae5a233d27a25ee160c68c6a7b5a73..4304f0751c5d4f5457696f8ac9e1b4ab38f843b7 100644
+--- a/dist/tsconfig.build.tsbuildinfo
++++ b/dist/tsconfig.build.tsbuildinfo
+@@ -1 +1 @@
+-{"program":{"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.esnext.intl.d.ts","../../../types/eth-ens-namehash.d.ts","../../../types/ethereum-ens-network-map.d.ts","../../../types/global.d.ts","../../../types/single-call-balance-checker-abi.d.ts","../../../types/@metamask/contract-metadata.d.ts","../../../types/@metamask/eth-hd-keyring.d.ts","../../../types/@metamask/eth-simple-keyring.d.ts","../../../types/@metamask/ethjs-provider-http.d.ts","../../../types/@metamask/ethjs-unit.d.ts","../../../types/@metamask/metamask-eth-abis.d.ts","../../../types/eth-json-rpc-infura/src/createProvider.d.ts","../../../types/eth-phishing-detect/src/config.json.d.ts","../../../types/eth-phishing-detect/src/detector.d.ts","../../../node_modules/@types/node/assert.d.ts","../../../node_modules/@types/node/assert/strict.d.ts","../../../node_modules/@types/node/globals.d.ts","../../../node_modules/@types/node/async_hooks.d.ts","../../../node_modules/@types/node/buffer.d.ts","../../../node_modules/@types/node/child_process.d.ts","../../../node_modules/@types/node/cluster.d.ts","../../../node_modules/@types/node/console.d.ts","../../../node_modules/@types/node/constants.d.ts","../../../node_modules/@types/node/crypto.d.ts","../../../node_modules/@types/node/dgram.d.ts","../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../node_modules/@types/node/dns.d.ts","../../../node_modules/@types/node/dns/promises.d.ts","../../../node_modules/@types/node/dom-events.d.ts","../../../node_modules/@types/node/domain.d.ts","../../../node_modules/@types/node/events.d.ts","../../../node_modules/@types/node/fs.d.ts","../../../node_modules/@types/node/fs/promises.d.ts","../../../node_modules/@types/node/http.d.ts","../../../node_modules/@types/node/http2.d.ts","../../../node_modules/@types/node/https.d.ts","../../../node_modules/@types/node/inspector.d.ts","../../../node_modules/@types/node/module.d.ts","../../../node_modules/@types/node/net.d.ts","../../../node_modules/@types/node/os.d.ts","../../../node_modules/@types/node/path.d.ts","../../../node_modules/@types/node/perf_hooks.d.ts","../../../node_modules/@types/node/process.d.ts","../../../node_modules/@types/node/punycode.d.ts","../../../node_modules/@types/node/querystring.d.ts","../../../node_modules/@types/node/readline.d.ts","../../../node_modules/@types/node/repl.d.ts","../../../node_modules/@types/node/stream.d.ts","../../../node_modules/@types/node/stream/promises.d.ts","../../../node_modules/@types/node/stream/consumers.d.ts","../../../node_modules/@types/node/stream/web.d.ts","../../../node_modules/@types/node/string_decoder.d.ts","../../../node_modules/@types/node/test.d.ts","../../../node_modules/@types/node/timers.d.ts","../../../node_modules/@types/node/timers/promises.d.ts","../../../node_modules/@types/node/tls.d.ts","../../../node_modules/@types/node/trace_events.d.ts","../../../node_modules/@types/node/tty.d.ts","../../../node_modules/@types/node/url.d.ts","../../../node_modules/@types/node/util.d.ts","../../../node_modules/@types/node/v8.d.ts","../../../node_modules/@types/node/vm.d.ts","../../../node_modules/@types/node/wasi.d.ts","../../../node_modules/@types/node/worker_threads.d.ts","../../../node_modules/@types/node/zlib.d.ts","../../../node_modules/@types/node/globals.global.d.ts","../../../node_modules/@types/node/index.d.ts","../../../node_modules/@ethereumjs/common/dist/enums.d.ts","../../../node_modules/@ethereumjs/common/dist/types.d.ts","../../../node_modules/buffer/index.d.ts","../../../node_modules/@ethereumjs/util/dist/constants.d.ts","../../../node_modules/@ethereumjs/util/dist/units.d.ts","../../../node_modules/@ethereumjs/util/dist/address.d.ts","../../../node_modules/@ethereumjs/util/dist/bytes.d.ts","../../../node_modules/@ethereumjs/util/dist/types.d.ts","../../../node_modules/@ethereumjs/util/dist/account.d.ts","../../../node_modules/@ethereumjs/util/dist/withdrawal.d.ts","../../../node_modules/@ethereumjs/util/dist/signature.d.ts","../../../node_modules/@ethereumjs/util/dist/encoding.d.ts","../../../node_modules/@ethereumjs/util/dist/asyncEventEmitter.d.ts","../../../node_modules/@ethereumjs/util/dist/internal.d.ts","../../../node_modules/@ethereumjs/util/dist/lock.d.ts","../../../node_modules/@ethereumjs/util/dist/provider.d.ts","../../../node_modules/@ethereumjs/util/dist/index.d.ts","../../../node_modules/@ethereumjs/common/dist/common.d.ts","../../../node_modules/@ethereumjs/common/dist/utils.d.ts","../../../node_modules/@ethereumjs/common/dist/index.d.ts","../../../node_modules/@ethereumjs/tx/dist/eip2930Transaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/legacyTransaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/types.d.ts","../../../node_modules/@ethereumjs/tx/dist/baseTransaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/eip1559Transaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/transactionFactory.d.ts","../../../node_modules/@ethereumjs/tx/dist/index.d.ts","../../base-controller/dist/types/BaseControllerV1.d.ts","../../../node_modules/superstruct/dist/error.d.ts","../../../node_modules/superstruct/dist/utils.d.ts","../../../node_modules/superstruct/dist/struct.d.ts","../../../node_modules/superstruct/dist/structs/coercions.d.ts","../../../node_modules/superstruct/dist/structs/refinements.d.ts","../../../node_modules/superstruct/dist/structs/types.d.ts","../../../node_modules/superstruct/dist/structs/utilities.d.ts","../../../node_modules/superstruct/dist/index.d.ts","../../../node_modules/@metamask/utils/dist/types/assert.d.ts","../../../node_modules/@metamask/utils/dist/types/base64.d.ts","../../../node_modules/@metamask/utils/dist/types/hex.d.ts","../../../node_modules/@metamask/utils/dist/types/bytes.d.ts","../../../node_modules/@metamask/utils/dist/types/caip-types.d.ts","../../../node_modules/@metamask/utils/dist/types/checksum.d.ts","../../../node_modules/@metamask/utils/dist/types/coercers.d.ts","../../../node_modules/@metamask/utils/dist/types/collections.d.ts","../../../node_modules/@metamask/utils/dist/types/encryption-types.d.ts","../../../node_modules/@metamask/utils/dist/types/errors.d.ts","../../../node_modules/@metamask/utils/dist/types/json.d.ts","../../../node_modules/@metamask/utils/dist/types/keyring.d.ts","../../../node_modules/@types/ms/index.d.ts","../../../node_modules/@types/debug/index.d.ts","../../../node_modules/@metamask/utils/dist/types/logging.d.ts","../../../node_modules/@metamask/utils/dist/types/misc.d.ts","../../../node_modules/@metamask/utils/dist/types/number.d.ts","../../../node_modules/@metamask/utils/dist/types/opaque.d.ts","../../../node_modules/@metamask/utils/dist/types/promise.d.ts","../../../node_modules/@metamask/utils/dist/types/time.d.ts","../../../node_modules/@metamask/utils/dist/types/transaction-types.d.ts","../../../node_modules/@metamask/utils/dist/types/versions.d.ts","../../../node_modules/@metamask/utils/dist/types/index.d.ts","../../../node_modules/immer/dist/utils/env.d.ts","../../../node_modules/immer/dist/utils/errors.d.ts","../../../node_modules/immer/dist/types/types-external.d.ts","../../../node_modules/immer/dist/types/types-internal.d.ts","../../../node_modules/immer/dist/utils/common.d.ts","../../../node_modules/immer/dist/utils/plugins.d.ts","../../../node_modules/immer/dist/core/scope.d.ts","../../../node_modules/immer/dist/core/finalize.d.ts","../../../node_modules/immer/dist/core/proxy.d.ts","../../../node_modules/immer/dist/core/immerClass.d.ts","../../../node_modules/immer/dist/core/current.d.ts","../../../node_modules/immer/dist/internal.d.ts","../../../node_modules/immer/dist/plugins/es5.d.ts","../../../node_modules/immer/dist/plugins/patches.d.ts","../../../node_modules/immer/dist/plugins/mapset.d.ts","../../../node_modules/immer/dist/plugins/all.d.ts","../../../node_modules/immer/dist/immer.d.ts","../../base-controller/dist/types/RestrictedControllerMessenger.d.ts","../../base-controller/dist/types/ControllerMessenger.d.ts","../../base-controller/dist/types/BaseControllerV2.d.ts","../../base-controller/dist/types/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/account.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/balance.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/caip.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/export.d.ts","../../../node_modules/@metamask/keyring-api/dist/superstruct.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/request.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/response.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/keyring.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/btc/types.d.ts","../../../node_modules/@metamask/keyring-api/dist/btc/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/contexts.d.ts","../../../node_modules/@metamask/keyring-api/dist/eth/erc4337/types.d.ts","../../../node_modules/@metamask/keyring-api/dist/eth/erc4337/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/eth/types.d.ts","../../../node_modules/@metamask/keyring-api/dist/eth/utils.d.ts","../../../node_modules/@metamask/keyring-api/dist/eth/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/events.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/api.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/eth/EthKeyring.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/eth/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/events.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/rpc.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/types.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/JsonRpcRequest.d.ts","../../../node_modules/@metamask/keyring-api/dist/KeyringClient.d.ts","../../../node_modules/@metamask/safe-event-emitter/dist/cjs/index.d.ts","../../json-rpc-engine/dist/types/JsonRpcEngine.d.ts","../../json-rpc-engine/dist/types/createAsyncMiddleware.d.ts","../../json-rpc-engine/dist/types/createScaffoldMiddleware.d.ts","../../json-rpc-engine/dist/types/getUniqueId.d.ts","../../json-rpc-engine/dist/types/idRemapMiddleware.d.ts","../../json-rpc-engine/dist/types/mergeMiddleware.d.ts","../../json-rpc-engine/dist/types/index.d.ts","../../../node_modules/@metamask/providers/dist/types/utils.d.ts","../../../node_modules/@metamask/providers/dist/types/BaseProvider.d.ts","../../../node_modules/@metamask/providers/dist/types/EIP6963.d.ts","../../../node_modules/@types/readable-stream/node_modules/safe-buffer/index.d.ts","../../../node_modules/@types/readable-stream/index.d.ts","../../../node_modules/@metamask/providers/dist/types/StreamProvider.d.ts","../../../node_modules/@metamask/providers/dist/types/extension-provider/createExternalExtensionProvider.d.ts","../../../node_modules/@metamask/providers/dist/types/MetaMaskInpageProvider.d.ts","../../../node_modules/@metamask/providers/dist/types/initializeInpageProvider.d.ts","../../../node_modules/@metamask/providers/dist/types/shimWeb3.d.ts","../../../node_modules/@metamask/providers/dist/types/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/KeyringSnapRpcClient.d.ts","../../../node_modules/@metamask/keyring-api/dist/rpc-handler.d.ts","../../../node_modules/@metamask/rpc-errors/dist/types/utils.d.ts","../../../node_modules/@metamask/rpc-errors/dist/types/classes.d.ts","../../../node_modules/@metamask/rpc-errors/dist/types/errors.d.ts","../../../node_modules/@metamask/rpc-errors/dist/types/error-constants.d.ts","../../../node_modules/@metamask/rpc-errors/dist/types/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/errors.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/error-wrappers.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/errors.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/helpers.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/structs.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/create-interface.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/dialog.d.ts","../../../node_modules/@metamask/key-tree/dist/constants.d.cts","../../../node_modules/@metamask/key-tree/node_modules/@noble/curves/abstract/modular.d.ts","../../../node_modules/@metamask/key-tree/node_modules/@noble/curves/abstract/utils.d.ts","../../../node_modules/@metamask/key-tree/node_modules/@noble/curves/abstract/curve.d.ts","../../../node_modules/@metamask/key-tree/dist/curves/ed25519.d.cts","../../../node_modules/@metamask/key-tree/dist/curves/ed25519Bip32.d.cts","../../../node_modules/@metamask/key-tree/node_modules/@noble/curves/abstract/weierstrass.d.ts","../../../node_modules/@metamask/key-tree/dist/curves/secp256k1.d.cts","../../../node_modules/@metamask/key-tree/dist/curves/curve.d.cts","../../../node_modules/@metamask/key-tree/dist/curves/index.d.cts","../../../node_modules/@metamask/key-tree/dist/utils.d.cts","../../../node_modules/@metamask/key-tree/dist/BIP44CoinTypeNode.d.cts","../../../node_modules/@metamask/key-tree/dist/SLIP10Node.d.cts","../../../node_modules/@metamask/key-tree/dist/BIP44Node.d.cts","../../../node_modules/@metamask/key-tree/dist/derivers/bip32.d.cts","../../../node_modules/@metamask/key-tree/dist/derivers/bip39.d.cts","../../../node_modules/@metamask/key-tree/dist/derivers/cip3.d.cts","../../../node_modules/@metamask/key-tree/dist/derivers/slip10.d.cts","../../../node_modules/@metamask/key-tree/dist/derivers/index.d.cts","../../../node_modules/@metamask/key-tree/dist/index.d.cts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/caip.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/permissions.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-bip32-entropy.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-bip32-public-key.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-bip44-entropy.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-client-status.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-entropy.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-file.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/component.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/Address.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/Box.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/Copyable.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/Divider.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/Button.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/Option.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/Dropdown.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/Input.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/Field.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/Form.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/formatting/Bold.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/formatting/Italic.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/formatting/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/Heading.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/Image.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/Link.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/Text.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/Value.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/Row.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/Spinner.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/jsx-runtime.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/jsx-dev-runtime.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/validation.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/nodes.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/address.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/copyable.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/divider.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/heading.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/image.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/panel.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/spinner.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/text.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/row.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/button.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/input.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/form.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/component.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/interface.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-interface-state.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-locale.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/snap.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-snaps.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/invoke-snap.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/invoke-keyring.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/manage-accounts.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/manage-state.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/notify.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/request-snaps.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/update-interface.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/methods.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/provider.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/global.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/images.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/cronjob.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/home-page.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/keyring.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/lifecycle.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/name-lookup.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/rpc-request.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/transaction.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/signature.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/user-input.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/jsx.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/svg.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/error-wrappers.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/images.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/snap-utils.d.ts","../../../node_modules/@metamask/keyring-api/dist/index.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/patchCBOR.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/lib/DataItem.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/lib/cbor-sync.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/lib/index.d.ts","../../../node_modules/@ngraveio/bc-ur/dist/ur.d.ts","../../../node_modules/@ngraveio/bc-ur/dist/urEncoder.d.ts","../../../node_modules/@ngraveio/bc-ur/dist/fountainEncoder.d.ts","../../../node_modules/@ngraveio/bc-ur/dist/fountainDecoder.d.ts","../../../node_modules/@ngraveio/bc-ur/dist/urDecoder.d.ts","../../../node_modules/@ngraveio/bc-ur/dist/index.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/RegistryType.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/RegistryItem.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/CryptoCoinInfo.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/PathComponent.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/CryptoKeypath.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/types.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/CryptoHDKey.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/CryptoECKey.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/Bytes.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/MultiKey.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/ScriptExpression.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/CryptoOutput.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/CryptoPSBT.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/CryptoAccount.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/Decoder/index.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/extended/CryptoMultiAccounts.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/errors/index.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/extended/DerivationSchema.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/extended/KeyDerivation.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/extended/QRHardwareCall.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/utils.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/index.d.ts","../../../node_modules/@keystonehq/bc-ur-registry-eth/dist/EthSignRequest.d.ts","../../../node_modules/@keystonehq/bc-ur-registry-eth/dist/EthSignature.d.ts","../../../node_modules/@keystonehq/bc-ur-registry-eth/dist/ETHNFTItem.d.ts","../../../node_modules/@keystonehq/bc-ur-registry-eth/dist/utlis.d.ts","../../../node_modules/@keystonehq/bc-ur-registry-eth/dist/index.d.ts","../../../node_modules/@keystonehq/base-eth-keyring/dist/InteractionProvider.d.ts","../../../node_modules/@keystonehq/base-eth-keyring/dist/BaseKeyring.d.ts","../../../node_modules/@keystonehq/base-eth-keyring/dist/index.d.ts","../../../node_modules/@metamask/obs-store/dist/ObservableStore.d.ts","../../../node_modules/@metamask/obs-store/dist/asStream.d.ts","../../../node_modules/@metamask/obs-store/dist/ComposedStore.d.ts","../../../node_modules/@metamask/obs-store/dist/MergedStore.d.ts","../../../node_modules/@metamask/obs-store/dist/transform.d.ts","../../../node_modules/@metamask/obs-store/dist/index.d.ts","../../../node_modules/@keystonehq/metamask-airgapped-keyring/dist/MetaMaskInteractionProvider.d.ts","../../../node_modules/@keystonehq/metamask-airgapped-keyring/dist/MetaMaskKeyring.d.ts","../../../node_modules/@keystonehq/metamask-airgapped-keyring/dist/index.d.ts","../../../node_modules/@metamask/browser-passworder/dist/index.d.ts","../../message-manager/dist/types/AbstractMessageManager.d.ts","../../controller-utils/dist/types/types.d.ts","../../controller-utils/dist/types/constants.d.ts","../../../node_modules/@metamask/eth-query/index.d.ts","../../../node_modules/@types/bn.js/index.d.ts","../../controller-utils/dist/types/util.d.ts","../../../node_modules/@spruceid/siwe-parser/dist/abnf.d.ts","../../../node_modules/@spruceid/siwe-parser/dist/utils.d.ts","../../../node_modules/@spruceid/siwe-parser/dist/parsers.d.ts","../../controller-utils/dist/types/siwe.d.ts","../../controller-utils/dist/types/index.d.ts","../../message-manager/dist/types/PersonalMessageManager.d.ts","../../message-manager/dist/types/TypedMessageManager.d.ts","../../message-manager/dist/types/EncryptionPublicKeyManager.d.ts","../../message-manager/dist/types/DecryptMessageManager.d.ts","../../message-manager/dist/types/index.d.ts","../../keyring-controller/dist/types/KeyringController.d.ts","../../keyring-controller/dist/types/index.d.ts","../../../node_modules/@metamask/object-multiplex/dist/Substream.d.ts","../../../node_modules/@metamask/object-multiplex/dist/ObjectMultiplex.d.ts","../../../node_modules/@metamask/object-multiplex/dist/index.d.ts","../../../node_modules/@metamask/post-message-stream/dist/utils.d.ts","../../../node_modules/@metamask/post-message-stream/dist/BasePostMessageStream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/window/WindowPostMessageStream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/WebWorker/WebWorkerPostMessageStream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/WebWorker/WebWorkerParentPostMessageStream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/node-process/ProcessParentMessageStream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/node-process/ProcessMessageStream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/node-thread/ThreadParentMessageStream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/node-thread/ThreadMessageStream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/runtime/BrowserRuntimePostMessageStream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/index.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/array.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/auxiliary-files.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/virtual-file/VirtualFile.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/virtual-file/index.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/base64.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/bytes.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/caveats.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/checksum.d.ts","../../../node_modules/cron-parser/types/common.d.ts","../../../node_modules/cron-parser/types/index.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/cronjob.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/deep-clone.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/default-endowments.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/derivation-paths.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/entropy.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/errors.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/handler-types.d.ts","../../../node_modules/@metamask/snaps-sdk/jsx.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/handlers.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/iframe.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/json.d.ts","../../../node_modules/nanoid/index.d.ts","../../approval-controller/dist/types/ApprovalController.d.ts","../../approval-controller/dist/types/errors.d.ts","../../approval-controller/dist/types/index.d.ts","../../../node_modules/@types/deep-freeze-strict/index.d.ts","../../permission-controller/src/permission-middleware.ts","../../permission-controller/src/SubjectMetadataController.ts","../../permission-controller/src/utils.ts","../../permission-controller/src/PermissionController.ts","../../permission-controller/src/Permission.ts","../../permission-controller/src/errors.ts","../../permission-controller/src/Caveat.ts","../../permission-controller/src/rpc-methods/getPermissions.ts","../../permission-controller/src/rpc-methods/requestPermissions.ts","../../permission-controller/src/rpc-methods/revokePermissions.ts","../../permission-controller/src/rpc-methods/index.ts","../../permission-controller/src/index.ts","../../../node_modules/@metamask/snaps-utils/dist/types/json-rpc.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/structs.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/manifest/validation.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/manifest/index.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/localization.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/logging.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/namespace.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/path.d.ts","../../../node_modules/@metamask/snaps-registry/dist/verify.d.ts","../../../node_modules/@metamask/snaps-registry/dist/index.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/types.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/snaps.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/strings.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/ui.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/validation.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/versions.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/Timer.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/ExecutionService.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/AbstractExecutionService.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/ProxyPostMessageStream.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/iframe/IframeExecutionService.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/iframe/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/proxy/ProxyExecutionService.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/offscreen/OffscreenExecutionService.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/offscreen/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/webworker/WebWorkerExecutionService.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/webworker/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/location/npm.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/location/location.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/location/http.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/location/local.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/location/index.d.ts","../../../node_modules/@xstate/fsm/lib/types.d.ts","../../../node_modules/@xstate/fsm/lib/index.d.ts","../../../node_modules/@types/punycode/index.d.ts","../../../node_modules/fastest-levenshtein/mod.d.ts","../../phishing-controller/src/utils.ts","../../phishing-controller/src/PhishingDetector.ts","../../phishing-controller/src/PhishingController.ts","../../phishing-controller/src/index.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/interface/SnapInterfaceController.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/interface/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/types/encryptor.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/types/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/registry/registry.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/registry/json.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/registry/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/SnapController.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/selectors.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/utils.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/cronjob/CronjobController.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/cronjob/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/index.d.ts","../../accounts-controller/dist/types/AccountsController.d.ts","../../../node_modules/@types/uuid/index.d.ts","../../accounts-controller/dist/types/utils.d.ts","../../accounts-controller/dist/types/index.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/types.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/createEventEmitterProxy.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/createSwappableProxy.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/index.d.ts","../../network-controller/dist/types/constants.d.ts","../../eth-json-rpc-provider/dist/types/safe-event-emitter-provider.d.ts","../../eth-json-rpc-provider/dist/types/provider-from-engine.d.ts","../../eth-json-rpc-provider/dist/types/provider-from-middleware.d.ts","../../eth-json-rpc-provider/dist/types/index.d.ts","../../../node_modules/@metamask/eth-block-tracker/dist/BlockTracker.d.ts","../../../node_modules/@metamask/eth-block-tracker/dist/PollingBlockTracker.d.ts","../../../node_modules/@metamask/eth-block-tracker/dist/SubscribeBlockTracker.d.ts","../../../node_modules/@metamask/eth-block-tracker/dist/index.d.ts","../../network-controller/dist/types/types.d.ts","../../network-controller/dist/types/create-auto-managed-network-client.d.ts","../../network-controller/dist/types/NetworkController.d.ts","../../network-controller/dist/types/create-network-client.d.ts","../../network-controller/dist/types/index.d.ts","../../polling-controller/dist/types/types.d.ts","../../polling-controller/dist/types/BlockTrackerPollingController.d.ts","../../polling-controller/dist/types/StaticIntervalPollingController.d.ts","../../polling-controller/dist/types/index.d.ts","../../gas-fee-controller/dist/types/GasFeeController.d.ts","../../gas-fee-controller/dist/types/index.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/MutexInterface.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/Mutex.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/SemaphoreInterface.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/Semaphore.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/withTimeout.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/tryAcquire.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/errors.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/index.d.ts","../../../node_modules/@metamask/nonce-tracker/dist/NonceTracker.d.ts","../../../node_modules/@metamask/nonce-tracker/dist/index.d.ts","../../../node_modules/async-mutex/lib/MutexInterface.d.ts","../../../node_modules/async-mutex/lib/Mutex.d.ts","../../../node_modules/async-mutex/lib/SemaphoreInterface.d.ts","../../../node_modules/async-mutex/lib/Semaphore.d.ts","../../../node_modules/async-mutex/lib/withTimeout.d.ts","../../../node_modules/async-mutex/lib/tryAcquire.d.ts","../../../node_modules/async-mutex/lib/errors.d.ts","../../../node_modules/async-mutex/lib/index.d.ts","../../../node_modules/eth-method-registry/dist/index.d.ts","../../../node_modules/@types/lodash/common/common.d.ts","../../../node_modules/@types/lodash/common/array.d.ts","../../../node_modules/@types/lodash/common/collection.d.ts","../../../node_modules/@types/lodash/common/date.d.ts","../../../node_modules/@types/lodash/common/function.d.ts","../../../node_modules/@types/lodash/common/lang.d.ts","../../../node_modules/@types/lodash/common/math.d.ts","../../../node_modules/@types/lodash/common/number.d.ts","../../../node_modules/@types/lodash/common/object.d.ts","../../../node_modules/@types/lodash/common/seq.d.ts","../../../node_modules/@types/lodash/common/string.d.ts","../../../node_modules/@types/lodash/common/util.d.ts","../../../node_modules/@types/lodash/index.d.ts","../src/logger.ts","../../../node_modules/fast-json-patch/module/helpers.d.ts","../../../node_modules/fast-json-patch/module/core.d.ts","../../../node_modules/fast-json-patch/module/duplex.d.ts","../../../node_modules/fast-json-patch/index.d.ts","../src/types.ts","../src/utils/gas-flow.ts","../src/constants.ts","../src/utils/utils.ts","../src/utils/swaps.ts","../src/utils/gas-fees.ts","../src/gas-flows/DefaultGasFeeFlow.ts","../src/gas-flows/LineaGasFeeFlow.ts","../../../node_modules/@ethersproject/bytes/lib/index.d.ts","../../../node_modules/@ethersproject/bignumber/lib/bignumber.d.ts","../../../node_modules/@ethersproject/bignumber/lib/fixednumber.d.ts","../../../node_modules/@ethersproject/bignumber/lib/index.d.ts","../../../node_modules/@ethersproject/abi/lib/fragments.d.ts","../../../node_modules/@ethersproject/abi/lib/coders/abstract-coder.d.ts","../../../node_modules/@ethersproject/abi/lib/abi-coder.d.ts","../../../node_modules/@ethersproject/properties/lib/index.d.ts","../../../node_modules/@ethersproject/abi/lib/interface.d.ts","../../../node_modules/@ethersproject/abi/lib/index.d.ts","../../../node_modules/@ethersproject/networks/lib/types.d.ts","../../../node_modules/@ethersproject/networks/lib/index.d.ts","../../../node_modules/@ethersproject/transactions/lib/index.d.ts","../../../node_modules/@ethersproject/web/lib/index.d.ts","../../../node_modules/@ethersproject/abstract-provider/lib/index.d.ts","../../../node_modules/@ethersproject/abstract-signer/lib/index.d.ts","../../../node_modules/@ethersproject/contracts/lib/index.d.ts","../../../node_modules/@ethersproject/providers/lib/formatter.d.ts","../../../node_modules/@ethersproject/providers/lib/base-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/json-rpc-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/websocket-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/url-json-rpc-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/alchemy-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/ankr-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/cloudflare-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/etherscan-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/fallback-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/ipc-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/infura-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/json-rpc-batch-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/nodesmith-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/pocket-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/web3-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/index.d.ts","../src/gas-flows/OracleLayer1GasFeeFlow.ts","../src/gas-flows/OptimismLayer1GasFeeFlow.ts","../src/gas-flows/ScrollLayer1GasFeeFlow.ts","../src/gas-flows/TestGasFeeFlow.ts","../src/utils/etherscan.ts","../src/helpers/EtherscanRemoteTransactionSource.ts","../src/utils/layer1-gas-fee-flow.ts","../src/helpers/GasFeePoller.ts","../src/helpers/IncomingTransactionHelper.ts","../src/helpers/PendingTransactionTracker.ts","../src/helpers/MultichainTrackingHelper.ts","../src/utils/external-transactions.ts","../src/utils/gas.ts","../src/utils/history.ts","../src/utils/nonce.ts","../../../node_modules/@metamask/metamask-eth-abis/dist/abis/abiERC20.d.ts","../../../node_modules/@metamask/metamask-eth-abis/dist/abis/abiERC721.d.ts","../../../node_modules/@metamask/metamask-eth-abis/dist/abis/abiERC1155.d.ts","../../../node_modules/@metamask/metamask-eth-abis/dist/abis/fiatTokenV2.d.ts","../../../node_modules/@metamask/metamask-eth-abis/dist/index.d.ts","../src/errors.ts","../src/utils/simulation-api.ts","../src/utils/simulation.ts","../src/utils/transaction-type.ts","../src/utils/validation.ts","../src/TransactionController.ts","../src/index.ts","../../../node_modules/@babel/types/lib/index.d.ts","../../../node_modules/@types/babel__generator/index.d.ts","../../../node_modules/@babel/parser/typings/babel-parser.d.ts","../../../node_modules/@types/babel__template/index.d.ts","../../../node_modules/@types/babel__traverse/index.d.ts","../../../node_modules/@types/babel__core/index.d.ts","../../../node_modules/@types/eslint/helpers.d.ts","../../../node_modules/@types/estree/index.d.ts","../../../node_modules/@types/json-schema/index.d.ts","../../../node_modules/@types/eslint/index.d.ts","../../../node_modules/@types/graceful-fs/index.d.ts","../../../node_modules/@types/istanbul-lib-coverage/index.d.ts","../../../node_modules/@types/istanbul-lib-report/index.d.ts","../../../node_modules/@types/istanbul-reports/index.d.ts","../../../node_modules/chalk/index.d.ts","../../../node_modules/jest-diff/build/cleanupSemantic.d.ts","../../../node_modules/pretty-format/build/types.d.ts","../../../node_modules/pretty-format/build/index.d.ts","../../../node_modules/jest-diff/build/types.d.ts","../../../node_modules/jest-diff/build/diffLines.d.ts","../../../node_modules/jest-diff/build/printDiffs.d.ts","../../../node_modules/jest-diff/build/index.d.ts","../../../node_modules/jest-matcher-utils/build/index.d.ts","../../../node_modules/@types/jest/index.d.ts","../../../node_modules/@types/jest-when/index.d.ts","../../../node_modules/@types/json5/index.d.ts","../../../node_modules/@types/minimatch/index.d.ts","../../../node_modules/@types/parse-json/index.d.ts","../../../node_modules/@types/pbkdf2/index.d.ts","../../../node_modules/@types/prettier/index.d.ts","../../../node_modules/@types/secp256k1/index.d.ts","../../../node_modules/@types/semver/classes/semver.d.ts","../../../node_modules/@types/semver/functions/parse.d.ts","../../../node_modules/@types/semver/functions/valid.d.ts","../../../node_modules/@types/semver/functions/clean.d.ts","../../../node_modules/@types/semver/functions/inc.d.ts","../../../node_modules/@types/semver/functions/diff.d.ts","../../../node_modules/@types/semver/functions/major.d.ts","../../../node_modules/@types/semver/functions/minor.d.ts","../../../node_modules/@types/semver/functions/patch.d.ts","../../../node_modules/@types/semver/functions/prerelease.d.ts","../../../node_modules/@types/semver/functions/compare.d.ts","../../../node_modules/@types/semver/functions/rcompare.d.ts","../../../node_modules/@types/semver/functions/compare-loose.d.ts","../../../node_modules/@types/semver/functions/compare-build.d.ts","../../../node_modules/@types/semver/functions/sort.d.ts","../../../node_modules/@types/semver/functions/rsort.d.ts","../../../node_modules/@types/semver/functions/gt.d.ts","../../../node_modules/@types/semver/functions/lt.d.ts","../../../node_modules/@types/semver/functions/eq.d.ts","../../../node_modules/@types/semver/functions/neq.d.ts","../../../node_modules/@types/semver/functions/gte.d.ts","../../../node_modules/@types/semver/functions/lte.d.ts","../../../node_modules/@types/semver/functions/cmp.d.ts","../../../node_modules/@types/semver/functions/coerce.d.ts","../../../node_modules/@types/semver/classes/comparator.d.ts","../../../node_modules/@types/semver/classes/range.d.ts","../../../node_modules/@types/semver/functions/satisfies.d.ts","../../../node_modules/@types/semver/ranges/max-satisfying.d.ts","../../../node_modules/@types/semver/ranges/min-satisfying.d.ts","../../../node_modules/@types/semver/ranges/to-comparators.d.ts","../../../node_modules/@types/semver/ranges/min-version.d.ts","../../../node_modules/@types/semver/ranges/valid.d.ts","../../../node_modules/@types/semver/ranges/outside.d.ts","../../../node_modules/@types/semver/ranges/gtr.d.ts","../../../node_modules/@types/semver/ranges/ltr.d.ts","../../../node_modules/@types/semver/ranges/intersects.d.ts","../../../node_modules/@types/semver/ranges/simplify.d.ts","../../../node_modules/@types/semver/ranges/subset.d.ts","../../../node_modules/@types/semver/internals/identifiers.d.ts","../../../node_modules/@types/semver/index.d.ts","../../../node_modules/@types/sinonjs__fake-timers/index.d.ts","../../../node_modules/@types/sinon/index.d.ts","../../../node_modules/@types/stack-utils/index.d.ts","../../../node_modules/@types/yargs-parser/index.d.ts","../../../node_modules/@types/yargs/index.d.ts"],"fileInfos":[{"version":"8730f4bf322026ff5229336391a18bcaa1f94d4f82416c8b2f3954e2ccaae2ba","affectsGlobalScope":true},"dc47c4fa66b9b9890cf076304de2a9c5201e94b740cffdf09f87296d877d71f6","7a387c58583dfca701b6c85e0adaf43fb17d590fb16d5b2dc0a2fbd89f35c467","8a12173c586e95f4433e0c6dc446bc88346be73ffe9ca6eec7aa63c8f3dca7f9","5f4e733ced4e129482ae2186aae29fde948ab7182844c3a5a51dd346182c7b06","4b421cbfb3a38a27c279dec1e9112c3d1da296f77a1a85ddadf7e7a425d45d18","1fc5ab7a764205c68fa10d381b08417795fc73111d6dd16b5b1ed36badb743d9",{"version":"3aafcb693fe5b5c3bd277bd4c3a617b53db474fe498fc5df067c5603b1eebde7","affectsGlobalScope":true},{"version":"adb996790133eb33b33aadb9c09f15c2c575e71fb57a62de8bf74dbf59ec7dfb","affectsGlobalScope":true},{"version":"8cc8c5a3bac513368b0157f3d8b31cfdcfe78b56d3724f30f80ed9715e404af8","affectsGlobalScope":true},{"version":"cdccba9a388c2ee3fd6ad4018c640a471a6c060e96f1232062223063b0a5ac6a","affectsGlobalScope":true},{"version":"c5c05907c02476e4bde6b7e76a79ffcd948aedd14b6a8f56e4674221b0417398","affectsGlobalScope":true},{"version":"5f406584aef28a331c36523df688ca3650288d14f39c5d2e555c95f0d2ff8f6f","affectsGlobalScope":true},{"version":"22f230e544b35349cfb3bd9110b6ef37b41c6d6c43c3314a31bd0d9652fcec72","affectsGlobalScope":true},{"version":"7ea0b55f6b315cf9ac2ad622b0a7813315bb6e97bf4bb3fbf8f8affbca7dc695","affectsGlobalScope":true},{"version":"3013574108c36fd3aaca79764002b3717da09725a36a6fc02eac386593110f93","affectsGlobalScope":true},{"version":"eb26de841c52236d8222f87e9e6a235332e0788af8c87a71e9e210314300410a","affectsGlobalScope":true},{"version":"3be5a1453daa63e031d266bf342f3943603873d890ab8b9ada95e22389389006","affectsGlobalScope":true},{"version":"17bb1fc99591b00515502d264fa55dc8370c45c5298f4a5c2083557dccba5a2a","affectsGlobalScope":true},{"version":"7ce9f0bde3307ca1f944119f6365f2d776d281a393b576a18a2f2893a2d75c98","affectsGlobalScope":true},{"version":"6a6b173e739a6a99629a8594bfb294cc7329bfb7b227f12e1f7c11bc163b8577","affectsGlobalScope":true},{"version":"81cac4cbc92c0c839c70f8ffb94eb61e2d32dc1c3cf6d95844ca099463cf37ea","affectsGlobalScope":true},{"version":"b0124885ef82641903d232172577f2ceb5d3e60aed4da1153bab4221e1f6dd4e","affectsGlobalScope":true},{"version":"0eb85d6c590b0d577919a79e0084fa1744c1beba6fd0d4e951432fa1ede5510a","affectsGlobalScope":true},{"version":"da233fc1c8a377ba9e0bed690a73c290d843c2c3d23a7bd7ec5cd3d7d73ba1e0","affectsGlobalScope":true},{"version":"d154ea5bb7f7f9001ed9153e876b2d5b8f5c2bb9ec02b3ae0d239ec769f1f2ae","affectsGlobalScope":true},{"version":"bb2d3fb05a1d2ffbca947cc7cbc95d23e1d053d6595391bd325deb265a18d36c","affectsGlobalScope":true},{"version":"c80df75850fea5caa2afe43b9949338ce4e2de086f91713e9af1a06f973872b8","affectsGlobalScope":true},{"version":"9d57b2b5d15838ed094aa9ff1299eecef40b190722eb619bac4616657a05f951","affectsGlobalScope":true},{"version":"6c51b5dd26a2c31dbf37f00cfc32b2aa6a92e19c995aefb5b97a3a64f1ac99de","affectsGlobalScope":true},{"version":"6e7997ef61de3132e4d4b2250e75343f487903ddf5370e7ce33cf1b9db9a63ed","affectsGlobalScope":true},{"version":"2ad234885a4240522efccd77de6c7d99eecf9b4de0914adb9a35c0c22433f993","affectsGlobalScope":true},{"version":"5e5e095c4470c8bab227dbbc61374878ecead104c74ab9960d3adcccfee23205","affectsGlobalScope":true},{"version":"09aa50414b80c023553090e2f53827f007a301bc34b0495bfb2c3c08ab9ad1eb","affectsGlobalScope":true},{"version":"d7f680a43f8cd12a6b6122c07c54ba40952b0c8aa140dcfcf32eb9e6cb028596","affectsGlobalScope":true},{"version":"3787b83e297de7c315d55d4a7c546ae28e5f6c0a361b7a1dcec1f1f50a54ef11","affectsGlobalScope":true},{"version":"e7e8e1d368290e9295ef18ca23f405cf40d5456fa9f20db6373a61ca45f75f40","affectsGlobalScope":true},{"version":"faf0221ae0465363c842ce6aa8a0cbda5d9296940a8e26c86e04cc4081eea21e","affectsGlobalScope":true},{"version":"06393d13ea207a1bfe08ec8d7be562549c5e2da8983f2ee074e00002629d1871","affectsGlobalScope":true},{"version":"2768ef564cfc0689a1b76106c421a2909bdff0acbe87da010785adab80efdd5c","affectsGlobalScope":true},{"version":"b248e32ca52e8f5571390a4142558ae4f203ae2f94d5bac38a3084d529ef4e58","affectsGlobalScope":true},{"version":"52d1bb7ab7a3306fd0375c8bff560feed26ed676a5b0457fa8027b563aecb9a4","affectsGlobalScope":true},"70bbfaec021ac4a0c805374225b55d70887f987df8b8dd7711d79464bb7b4385","869089d60b67219f63e6aca810284c89bae1b384b5cbc7ce64e53d82ad223ed5",{"version":"f31113ac9492fdd6e78bf6151b338c92e5b1837be426ef4aa0648ce82d13b518","affectsGlobalScope":true},"62a0875a0397b35a2364f1d401c0ce17975dfa4d47bf6844de858ae04da349f9","ee7491d0318d1fafcba97d5b72b450eb52671570f7a4ecd9e8898d40eaae9472","e3e7d217d89b380c1f34395eadc9289542851b0f0a64007dfe1fb7cf7423d24e","fd79909e93b4d50fd0ed9f3d39ddf8ba0653290bac25c295aac49f6befbd081b","345a9cc2945406f53051cd0e9b51f82e1e53929848eab046fdda91ee8aa7da31","9debe2de883da37a914e5e784a7be54c201b8f1d783822ad6f443ff409a5ea21","dee5d5c5440cda1f3668f11809a5503c30db0476ad117dd450f7ba5a45300e8f","f5e396c1424c391078c866d6f84afe0b4d2f7f85a160b9c756cd63b5b1775d93","5caa6f4fff16066d377d4e254f6c34c16540da3809cd66cd626a303bc33c419f","730d055528bdf12c8524870bb33d237991be9084c57634e56e5d8075f6605e02","5b3cd03ae354ea96eff1f74d7c410fe4852e6382227e8b0ecf87ab5e3a5bbcd4","7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419",{"version":"056097110efd16869ec118cedb44ecbac9a019576eee808d61304ca6d5cb2cbe","affectsGlobalScope":true},"f51b4042a3ac86f1f707500a9768f88d0b0c1fc3f3e45a73333283dea720cdc6",{"version":"6fb8358e10ed92a7f515b7d79da3904c955a3ffd4e14aa9df6f0ea113041f1cf","affectsGlobalScope":true},"45c831238c6dac21c72da5f335747736a56a3847192bf03c84b958a7e9ec93e2","661a11d16ad2e3543a77c53bcd4017ee9a450f47ab7def3ab493a86eae4d550c",{"version":"8cdc646cec7819581ef343b83855b1bfe4fe674f2c84f4fb8dc90d82fb56bd3a","affectsGlobalScope":true},"a40826e8476694e90da94aa008283a7de50d1dafd37beada623863f1901cb7fb","9dd56225cc2d8cb8fe5ceb0043ff386987637e12fecc6078896058a99deae284","2375ed4b439215aa3b6d0c6fd175c78a4384b30cb43cbadaecbf0a18954c98cb","7693b90b3075deaccafd5efb467bf9f2b747a3075be888652ef73e64396d8628","41231da15bb5e3e806a8395bd15c7befd2ec90f9f4e3c9d0ae1356bccb76dbb0","fccfef201d057cb407fa515311bd608549bab6c7b8adcf8f2df31f5d3b796478",{"version":"ee1ee365d88c4c6c0c0a5a5701d66ebc27ccd0bcfcfaa482c6e2e7fe7b98edf7","affectsGlobalScope":true},"5f20d20b7607174caf1a6da9141aeb9f2142159ae2410ca30c7a0fccd1d19c99",{"version":"464762c6213566d072f1ced5e8e9a954785ec5e53883b7397198abb5ef5b8f71","affectsGlobalScope":true},"6387920dc3e18927335b086deec75bf8e50f879a5e273d32ee7bb7a55ba50572","9bba37424094688c4663c177a1379b229f919b8912889a472f32fdc5f08ddb4d","29a4be13b3a30d3e66667b75c58ec61fb2df8fa0422534fdee3cfb30c5dbf450","83366d901beda79d6eb37aaaf6ca248dcd88946302b2a7d975590783be51e88e","bf268a0aea37ad4ae3b7a9b58559190b6fc01ea16a31e35cd05817a0a60f895a","43ec77c369473e92e2ecebf0554a0fdaa9c256644a6070f28228dfcceec77351",{"version":"d7dad6db394a3d9f7b49755e4b610fbf8ed6eb0c9810ae5f1a119f6b5d76de45","affectsGlobalScope":true},"95ed02bacb4502c985b69742ec82a4576d4ff4a6620ecc91593f611d502ae546","bf755525c4e6f85a970b98c4755d98e8aa1b6dbd83a5d8fcc57d3d497351b936","dd67d2b5e4e8a182a38de8e69fb736945eaa4588e0909c14e01a14bd3cc1fd1e",{"version":"28084e15b63e6211769db2fe646d8bc5c4c6776321e0deffe2d12eefd52cb6b9","affectsGlobalScope":true},{"version":"aed37dabf86c99d6c8508700576ecede86688397bc12523541858705a0c737c2","affectsGlobalScope":true},"cc6ef5733d4ea6d2e06310a32dffd2c16418b467c5033d49cecc4f3a25de7497","94768454c3348b6ebe48e45fbad8c92e2bb7af4a35243edbe2b90823d0bd7f9a","0be79b3ff0f16b6c2f9bc8c4cc7097ea417d8d67f8267f7e1eec8e32b548c2ff","1c61ffa3a71b77363b30d19832c269ef62fba787f5610cac7254728d3b69ab2e","84da3c28344e621fd1d591f2c09e9595292d2b70018da28a553268ac122597d4","269929a24b2816343a178008ac9ae9248304d92a8ba8e233055e0ed6dbe6ef71","6e191fea1db6e9e4fa828259cf489e820ec9170effff57fb081a2f3295db4722","aed943465fbce1efe49ee16b5ea409050f15cd8eaf116f6fadb64ef0772e7d95","70d08483a67bf7050dbedace398ef3fee9f436fcd60517c97c4c1e22e3c6f3e8","c40fdf7b2e18df49ce0568e37f0292c12807a0748be79e272745e7216bed2606",{"version":"e933de8143e1d12dd51d89b398760fd5a9081896be366dad88a922d0b29f3c69","affectsGlobalScope":true},"4e228e78c1e9b0a75c70588d59288f63a6258e8b1fe4a67b0c53fe03461421d9","b38d55d08708c2410a3039687db70b4a5bfa69fc4845617c313b5a10d9c5c637","205d50c24359ead003dc537b9b65d2a64208dfdffe368f403cf9e0357831db9e","1265fddcd0c68be9d2a3b29805d0280484c961264dd95e0b675f7bd91f777e78",{"version":"a05e2d784c9be7051c4ac87a407c66d2106e23490c18c038bbd0712bde7602fd","affectsGlobalScope":true},{"version":"df90b9d0e9980762da8daf8adf6ffa0c853e76bfd269c377be0d07a9ad87acd2","affectsGlobalScope":true},"cf434b5c04792f62d6f4bdd5e2c8673f36e638e910333c172614d5def9b17f98","1d65d4798df9c2df008884035c41d3e67731f29db5ecb64cd7378797c7c53a2f","0faee6b555890a1cb106e2adc5d3ffd89545b1da894d474e9d436596d654998f","c6c01ea1c42508edf11a36d13b70f6e35774f74355ba5d358354d4a77cc67ea1","867f95abf1df444aab146b19847391fc2f922a55f6a970a27ed8226766cee29f",{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true},"b0297b09e607bec9698cac7cf55463d6731406efb1161ee4d448293b47397c84","175323e2a79a6076e0bada8a390d535a3ea817158bf1b1f46e31efca9028a0a2","7a10053aadc19335532a4d02756db4865974fd69bea5439ddcc5bfdf062d9476","4967529644e391115ca5592184d4b63980569adf60ee685f968fd59ab1557188","aed9e712a9b168345362e8f3a949f16c99ca1e05d21328f05735dfdbb24414ef","b04fe6922ed3db93afdbd49cdda8576aa75f744592fceea96fb0d5f32158c4f5","ed8d6c8de90fc2a4faaebc28e91f2469928738efd5208fb75ade0fa607e892b7","d7c52b198d680fe65b1a8d1b001f0173ffa2536ca2e7082431d726ce1f6714cd","c07f251e1c4e415a838e5498380b55cfea94f3513229de292d2aa85ae52fc3e9","0ed401424892d6bf294a5374efe512d6951b54a71e5dd0290c55b6d0d915f6f7","b945be6da6a3616ef3a250bfe223362b1c7c6872e775b0c4d82a1bf7a28ff902","beea49237dd7c7110fabf3c7509919c9cb9da841d847c53cac162dc3479e2f87","0f45f8a529c450d8f394106cc622bff79e44a1716e1ac9c3cc68b43f7ecf65ee","c624ce90b04c27ce4f318ba6330d39bde3d4e306f0f497ce78d4bda5ab8e22ca","9b8253aa5cb2c82d505f72afdbf96e83b15cc6b9a6f4fadbbbab46210d5f1977","86a8f52e4b1ac49155e889376bcfa8528a634c90c27fec65aa0e949f77b740c5","aab5dd41c1e2316cc0b42a7dd15684f8582d5a1d16c0516276a2a8a7d0fecd9c","59948226626ee210045296ba1fc6cb0fe748d1ff613204e08e7157ab6862dee7","ec3e54d8b713c170fdc8110a7e4a6a97513a7ab6b05ac9e1100cb064d2bb7349","43beb30ecb39a603fde4376554887310b0699f25f7f39c5c91e3147b51bb3a26","666b77d7f06f49da114b090a399abbfa66d5b6c01a3fd9dc4f063a52ace28507","31997714a93fbc570f52d47d6a8ebfb021a34a68ea9ba58bbb69cdec9565657e","6032e4262822160128e644de3fc4410bcd7517c2f137525fd2623d2bb23cb0d3","8bd5c9b1016629c144fd228983395b9dbf0676a576716bc3d316cab612c33cd5","2ed90bd3925b23aed8f859ffd0e885250be0424ca2b57e9866dabef152e1d6b7","93f6bd17d92dab9db7897e1430a5aeaa03bcf51623156213d8397710367a76ce","3f62b770a42e8c47c7008726f95aa383e69d97e85e680d237b99fcb0ee601dd8","5b84cfe78028c35c3bb89c042f18bf08d09da11e82d275c378ae4d07d8477e6c","75b22c74010ba649de1a1676a4c4b8b5bb4294fecd05089e2094429b16d7840c","5615ccf831db2ffc82145243081ebdb60ea8e1005ee8f975d1c0c1401a9c894e","38682ed3630bb6ecdace80d5a9adc811fc20a419f1940446e306c3a020d083b9","cc182e6e4f691cd6f7bf7cb491247a4c7818f9f1cb2db1d45c65ff906e3f741b","a50599c08934a62f11657bdbe0dc929ab66da1b1f09974408fd9a33ec1bb8060","5a20e7d6c630b91be15e9b837853173829d00273197481dc8d3e94df61105a71","8d478048d71cc16f806d4b71b252ecb67c7444ccf4f4b09b29a312712184f859","e0eda929c6b9b628cdeb0e54cd3582cb97e64f28aab34612fc1431c545899584","9df4662ca3dbc2522bc115833ee04faa1afbb4e249a85ef4a0a09c621346bd08","b25d9065cf1c1f537a140bbc508e953ed2262f77134574c432d206ff36f4bdbf","1b103313097041aa9cd705a682c652f08613cb5cf8663321061c0902f845e81c","68ccec8662818911d8a12b8ed028bc5729fb4f1d34793c4701265ba60bc73cf4","5f85b8b79dc4d36af672c035b2beb71545de63a5d60bccbeee64c260941672ab","b3d48529ae61dc27d0bfbfa2cb3e0dff8189644bd155bdf5df1e8e14669f7043","40fe4b689225816b31fe5794c0fbf3534568819709e40295ead998a2bc1ab237","f65b5e33b9ad545a1eebbd6afe857314725ad42aaf069913e33f928ab3e4990a","fb6f2a87beb7fb1f4c2b762d0c76a9459fc91f557231569b0ee21399e22aa13d","31c858dc85996fac4b7fa944e1016d5c72f514930a72357ab5001097bf6511c7","3de30a871b3340be8b679c52aa12f90dd1c8c60874517be58968fdbcc4d79445","6fd985bd31eaf77542625306fb0404d32bff978990f0a06428e5f0b9a3b58109","980d21b0081cbf81774083b1e3a46f4bbdcd2b68858df0f66d7fad9c82bc34bc","68cc8d6fcc2f270d7108f02f3ebc59480a54615be3e09a47e14527f349e9d53e","3eb11dbf3489064a47a2e1cf9d261b1f100ef0b3b50ffca6c44dd99d6dd81ac1","b17f3bb7d8333479c7e45e5f3d876761b9bca58f97594eca3f6a944fd825e632","3c1f1236cce6d6e0c4e2c1b4371e6f72d7c14842ecd76a98ed0748ee5730c8f3","6d7f58d5ea72d7834946fd7104a734dc7d40661be8b2e1eaced1ddce3268ebaf","4c26222991e6c97d5a8f541d4f2c67585eda9e8b33cf9f52931b098045236e88","277983d414aa99d78655186c3ee1e1c38c302e336aff1d77b47fcdc39d8273fe","47383b45796d525a4039cd22d2840ac55a1ff03a43d027f7f867ba7314a9cf53","6548773b3abbc18de29176c2141f766d4e437e40596ee480447abf83575445ad","6ddd27af0436ce59dd4c1896e2bfdb2bdb2529847d078b83ce67a144dff05491","816264799aef3fd5a09a3b6c25217d5ec26a9dfc7465eac7d6073bcdc7d88f3f","4df0891b133884cd9ed752d31c7d0ec0a09234e9ed5394abffd3c660761598db","b603b62d3dcd31ef757dc7339b4fa8acdbca318b0fb9ac485f9a1351955615f9","e642bd47b75ad6b53cbf0dfd7ddfa0f120bd10193f0c58ec37d87b59bf604aca","be90b24d2ee6f875ce3aaa482e7c41a54278856b03d04212681c4032df62baf9","78f5ff400b3cb37e7b90eef1ff311253ed31c8cb66505e9828fad099bffde021","372c47090e1131305d163469a895ff2938f33fa73aad988df31cd31743f9efb6","71c67dc6987bdbd5599353f90009ff825dd7db0450ef9a0aee5bb0c574d18512","6f12403b5eca6ae7ca8e3efe3eeb9c683b06ce3e3844ccfd04098d83cd7e4957","282c535df88175d64d9df4550d2fd1176fd940c1c6822f1e7584003237f179d3","c3a4752cf103e4c6034d5bd449c8f9d5e7b352d22a5f8f9a41a8efb11646f9c2","11a9e38611ac3c77c74240c58b6bd64a0032128b29354e999650f1de1e034b1c","4ed103ca6fff9cb244f7c4b86d1eb28ce8069c32db720784329946731badb5bb","d738f282842970e058672663311c6875482ee36607c88b98ffb6604fba99cb2a","ec859cd8226aa623e41bbb47c249a55ee16dc1b8647359585244d57d3a5ed0c7","8891c6e959d253a66434ff5dc9ae46058fb3493e84b4ca39f710ef2d350656b1","c4463cf02535444dcbc3e67ecd29f1972490f74e49957d6fd4282a1013796ba6","0cb0a957ff02de0b25fd0f3f37130ca7f22d1e0dea256569c714c1f73c6791f8","2f5075dc512d51786b1ba3b1696565641dfaae3ac854f5f13d61fa12ef81a47e","ca3353cc82b1981f0d25d71d7432d583a6ef882ccdea82d65fbe49af37be51cb","50679a8e27aacf72f8c40bcab15d7ef5e83494089b4726b83eec4554344d5cdc","45351e0d51780b6f4088277a4457b9879506ee2720a887de232df0f1efcb33d8","e2d6963e7bf7186e30b7a4c9859aba4e96eda6d1be537e5b1a43bdddc7e9dc8f","10afdd7bba6ec9b7f95a4b419b2dbb64245fea4a61bbe7d68e2f841b414f7312","413121b26b3bd9f7fea237f15f564ee2b95bcd0cceec1b1621075375ccc0c0e0","d2af215963d01cef397ce8fa2f7ad08ee8beffdd39fe14b96021ddf26554b59f","2fc9848431d0f5e2b49bb312aaf07dd2d5a34300a2ced60200a2da49e6a82b43","c5ee2b685431ea2b9aacd9bb9e15cac1ecfa5c448972b188432313354d47c848","3e69be1137d88eb0730332aed359caedea4a27903da15dbe6a1615fa11206807","2283d079c3945b6e5ca8b9355311a213e03b74bffc65a3234c3c141a0a795700","f47272f05bd57f4356abc81232bded724d13e54f0fd801e0fb93a58237db1829","07ae8e9890f49ef6ebe629e339ac590025606a1e96754965bbb2bf889199ced2","d5c19655468e29f60c871b21e73af8ebc653f736e7123ade916f22c4a5f80ce5","6a8649609161e2794b383ba275b0a6cb4a072dde7b954648f83dc6cdf1bfe4a8","601d4a40a69c782addaf84185d4547568ec072095ab9976610d89922d1291f8b","d5c19655468e29f60c871b21e73af8ebc653f736e7123ade916f22c4a5f80ce5","b5c9c8c4a2cd1cb9f76d849fb472d475c3cebdd48306414a4a19bd11d82c4055","b61e6a808f5f50873ac03f35d5a38fa8d4dd23a24f80ab69df1a032e8c71562d","c8be9283a381044a392a0687af5d98d3f51cbada2320b1801a82c948b6e39499","85052c71d72b9b017c88179f57a464d66e22619c7acd7d83b117a79cf1608979","502cd7c30fe21e2c36b62913d0cb5d20affc8779b3ad40881b26d90a22de3aaa","6d3101b183ea67ef606b93fe42127f30b2db5ac3b72c34ca9d6d8b00eb85d0f6","f5d7a36ff056cc314b0f61c89a03c4c36a24183b246e61d958e75e86521304cd","ff30e8237e23dde68041b5f09526ee86835b12c5d8b6421c1153093fdbeb9438","f516fc1e77e5ffd71fbe705b679797c3c5eb76bf76a88549e6316a29f3e197f7","b5b1110565ac688b660a893654a6c1bce6747f3aa6f847001a8a5ff4412394ba","3a971ea3e36685b96f24fbd53a94ad8dc061711b84e51fde4cf201f7041e618d","9b6c162d20e2ad4abdcff61a24082564ac59e63092220618162aef6e440c9228","7804ff981554ba1a0592481072806fc39dc1484791beda43eb7a60e16e70a360","fcc8beef29f39f09b1d9c9f99c42f9fed605ab1c28d2a630185f732b9ba53763","d6e6620a30d582182acc3f0a992a0c311adc589f111096aea11ab83fc09a5ccc","6213b8f686f56beab22b59a0f468590fd3a4c5fa931236a017efeca91d7c9584","c451cec9a588b1f105a5ea2c6063d4fca112b9d70105cacdadda0e1ef67e9379","cb047832dc68f5a2c41c62c5e95ddcacbae3a8b034d40cd15319a8cb7f25104a","980336ccdfc3c08f3c3b201aa6662e6016e20f15847f8465b68f3e8e67b4665c","5a3493939995f46ff3d9073cd534fb8961c3bf4e08c71db27066ff03d906dea8","8f333214062532989f190aed5f99c62eb820722e41956e8229e17cd246fbdd10","d1f010c19eb9c8190bd0859fa3b6f4975543b912b8b85e20bbb0b5bfbdf4d2b3","de4ccc96cef3f97fab148640799abb32a24b567a902a8233913f98481e3131bf",{"version":"801934aa449fe6df584bccdcc5d5b9280295cb7ac84918b6014fc5086e6f9ff6","affectsGlobalScope":true},"5e379df3d61561c2ed7789b5995b9ba2143bbba21a905e2381e16efe7d1fa424","f07a137bbe2de7a122c37bfea00e761975fb264c49f18003d398d71b3fb35a5f","6af760fb9ea02dc807c5053d8aee86389c4fce72fbb26af7b9568cac6c4710d5","c62c4ba5e910b4523f7e7adf4a55ec45c2bac99d9d8e9b0fe0c2a800a6f641b9","92131434f876fdd6fcbc40bd54a9d7500c66974362b16bd42641f990468587f4","8cf023c0bd57992fdd2ce6a7030a1874f49c8edc62eaffa9bfffcf18d2a2a1a2","8ea8f3040e38fb50d7dc3653f3b8a0dbb5244e82111576f99ce096bdc0fbf94c","48ed788ad126545a6156fcc37cd3bcf17de18a3e3fe6b6ef62cfb8140d1a45a2","63c271a745f628ffd4bd7ad0a63b021c362c9bd6bf8b18441a7162892395a214","8d3457e6c7c5cb890729fb60cb8db18f261226a3ea3ff6a4db4b84ea78313ace","9f9e5bae412fa5909fae636d6733aee27a108cc2ed5b13980611016336774d3c","662fe197bba64bd3f17ee118058cd2d0d2dbe33d7c0c865fd6365d90bfc44e1e","030519c351f800551cac2658038804969ca4584d2c0175a710602ac234ca1340","0278a6939ca83cd040b08ff8c5fc7838b6693ddc52f22526bf158e6b10e0246c","c2d6206e5ba4fd3063b01218c2b3b997afc1cfbeb49fcee991fa8595842ce53d","6a8096993458a3d71229031aa7415974eb5b47b320213e29660adfb519d6a3f4","cb7996a1af5b1d276483cd0c9b9de6540eff021abc90a720511ff4464519a2ff","9df6ec68878d65bc690ea3a33ce3ef5aa8254c36bc5f8346c0c2fd1f3b88a35c","a4fad04c4acc8a4b195cbbccef4c55019104753d547d5c94441643ccc89108a0","0244c23ea642361f7c192c1f0cfff9c12cfa5f51f9b155edd5c0a89fef308d34","c7298e68632ab03155f6de963d3d09cc4a5874c28a81524f56c667d8a052e538","3c69a83bde847af6fc3a53e1bb6b13cd06d38a27a142814b8dacc374f3b93284","5b46f7113f54565e7ffc83f2b474f557a1f54c7e5946769d5be220454656be73","fb58035d39c5759283cb73cfb3548aefe370aa3ad4e81fdb4e46f0979eb7669f","1311c325948b2d5576cebc70b1bf968d3446b4630802bef54120daf04ce1f625","d0b3609e8e7afed0fd0570152255458407e67249b94f6603afdfd68599423f21","17f4c5a1d6eaa87ea27eadcdff9085af3190533d98f799dda79a3af6f9a630ea","3e6f734ddf40e2e99ff7fff9568b7d9720663af9a0632c26a352c8d3270a3f0e","ec13f78303abcf550c5569dfae1446b8ceb89050f68ce04491481e72e8122ae2","a3fc57dbaa7f1efb010399ad4ef4fd9b462aa4e93bf74a9a34b099b97ffcc9cb","ffddd7ec6a450b0cb6f2f73f80de1df963ead312d7c81a8440268f34146ecb87","5d6a36ca0087fd6876df654d1b4192f0e402adfde994ad47e5c065da33692f9c","eb157a09c5f543d98644e2a99a785f9e0e91f054f9fecbf1c3e15831ff5d63a7","edd5530e2b1ccdf65093296e40a8634fcb11ecda3c164c31383a8c34cb04bc9d","9dfaf96d090fe8d96143465d85b4837661ae535143eea9ef99cd20df2e66338e","209d45c27e03c1417c42985252de6c25a2ec23abdc199d88e6139c88b93abd11","0ee5cdba58cfde3012bb9ff2e9edcc4e35a651373a2aa2c83ff9eb7df635419a","540f4dca27ea5a232828b6d91e1b2fce2720bdabaa4c1f3fbf59b672cc58bd8a","ba086b99d545ec6c9ff356989f076b5652ea1b09bcc65b87dfc43a5195a2efcc","c85d9776b36166b928ab1488d9224ebf970d41b0a35f09a3ee0b9bee3e698061","683196f606c5dab1c8c4a24a66d26e00f16f2d4b2a5abe25ebedd37d2954f930","9c3a1b01cba1238fb723ce06b6c163ef6c53be755394406782564d5c42c636b2","6e795e6270d39e918c7a0e62ac73793cda06fcf4b3692ee46583e15f5bf57ab8","0e821ef1eb67fa6144ea4de4277d913f5b1982d7407afd5f93754a8239d41554","5c09195ef359ffa9c6bbdb4fefb101d87ede4b9e9c28213faf5b45d102e4c609","80b4d93a4dcc90a12f6f4bb7c6851a8182ae29e556716d0d80b5c012a5ef554a","2556ef9d1820e0b6bbca6dd65a50ea64f525c4d8247ab50dff44c3f0d14a5643","cbd1c836db190d6e3add07165afc228f04e1f6170e1fe3aa5e6fc24a7e9573a3","9b13881feb958237232586d888a10a39d47cdffe3ee34688ed41888fa7baad94","122fe82cf5af80f0b26832b258b537b7dfe3ec28449c301b259ab10204b50d45","c467dada8fea6d60dff8a8be2675f737cacc76e14e50b72daa0f0710376df84b","9cb80bba611c2dd155a446ce424fe4bb1df2129751bc9416b7e42c055d1ddbff","6ee568039016b81ed70292a595ab781ab978cba4243a5fe49507040ee4f7ac8a","043783bebe87efb440183c9ebc8c4fdc1bb92060a5a0f7ce847e30dee7013ac3","e3dc0a97a59dea936b4fb7b1f6f4117b4aac9c86d0cd08b69bab2d0532a8a5e3","5d897601f8a4fe913057019d8211b99b06e3138f625a0cfb601d074f4278271d","a68bb369c4ba8ab43a78f3fad2d3ec130e1418bc946521b9c84e9b336d6e88f1","65f219e6e1f9d27c677a49d41ae7989b83bf6baa56debbeb50d95c3ab21632e2","cfde5d194dd858ad68f910defaed5b0d28730f8bf38359a9265a93ab29bc7bef","c89354ae268153d965011e484150f0c92faa87f3f66507c25b496973178e0400","f20aae41b169cddcbf3fde8ac380443182c8d7225194e788c404d9e11e6dc75d","a6f4816a634bb1ceb513634c1ef7c0535f461ed2565336eed69f6ac2babbe15b","c48566cb13403fca44192b4528e3f2ac993869d39526bd42cd2f2167c0285add","efae20e0c581240c7522e04829da4f0453ca263068596554d4b0e27878c7dfac","3af68ef927788cda7daab34be513fa4508229fdc6e5130d564a0a1ccb3fefafe","bbbd2cbb15a37d5f4dd54ad8c7c537d3df8352117523030fcec7dcbe62a05a58","b50d24ebc117f8805332e7e260e9587f572bb7b2ff0ca1ff6cfafb38015781f3","5cc8b8e18fe7fefab4b3c53a39467b5a0deb4200abae7f063ff0624b9e856c51","8e990781eb0107c25429b1274a31a4f3866a9a46290cce40f354b2a6e71c6c21","608c45069e89c4c8f0ab29f896cc93c6553808072d6304b23611b6c6de3c24bb","22cbabe752781b5f35482af9d1fcf1455cb1ece74e8b84700d4abcb44abe3776","b9ce4613536386a98897f1e3d8f61a851ce6cb34dc3c9db4f2ef5f55f007e9e1","a5d1209c7bf277af86281392d46e12ce3dd6052586053f757fb2e606cc75c0f3","31b5f53e3d57470830e87f9e03c02d4569ac81d4a758fdda75092f9a3f58beba","d765fbab22fd7003a65ed670100362ec1c90d55a772e6773a774135594e7ea41","c1f11d9b42bfb0823d34d93c58df91ffb6690b5a717b7d310d83f258f1784e58","775b207f00d4df5b3b0b536aa696d572cdd2cabe8ea18dd28e8b52f691fa2a55","f75cd30f162c2af5e5aca39c01c1a521bfa034fae523793de872815a3468bc08","0cf1123db73dabd86466a462375a6addae52f58d23030c6033f8aadc23539a36","e29cef4158591ed213b1c2cba8988237b1ff369f7a6ecd8cb8ac0302bad1fba8","5307876e4d0021ea01235eb2f7c24671f3d8b37590f4b446cd132a4e1dc9a335","92550acd737790dc60c4c130e6aac78656dd48a8334a4882f40e7f86bdf7a590","3df821880914f8bb3c8107b1107be75c8ddbe2120a2cefabbaf9b65936b5f4dd","f46ba7c6fa7fcc8b3d57c4618c18db3f4d8bfe1fcab5551d7f6d9a82cf4d6078","078b7043bea0968860374bf4671ed74dd9f6be4e28ab659517d81f74be463c51","68b139ebb9a7f3ee4ded6286d74f978a47968727665120f3bfc560476ce33c4d","56d02c29b2fd39b1b1a1265df291f3f98e6ec3e6119aff9f4cfa44fe888efaa7","2d01884891da6495cb4a2f060e4898209a507e711464c4c1480df85264e863ed","c485c6497f7587314c4c4a59b74850cbca4c0c4bc08146a918cfd237ef821dbb","e9eec004735b1bf7015edf5400aeb914a53132134d230e93786590d904d094cc","080b1aa93227952b4dd74b9d2c6e4f6002eb8403533749116a1c53bb9961c02d","874087eec1d457f6e3baf5ac46c42ea200e55040b394fac667aa3a64c49f5f6c","6e8a5b04a18abb192abc89d7219b9c6f633cb3136777ec808673a65f111ca749","4e7ac7e5dd58a6c29c724728b031669e3068b194b62c2b83f92e76a36cb34dbb","d74d2a92b54f95e47d2b76bd5ee516aab7ae93afb79cd34c6681dd29eb09e72a","747e6326a724bc54f799a466a5b5c4978a601a04a063a5bdabe150af2f25b9e2","b57e22e53b56cca7a57bfcfb234aa6a66f9b9e4c07159d7388f94f17a3eaee2c","e47709ec4d1618ef429648cd8ef967aef2005526b34fcbfac33037add347dc71","b81abb3e47fbbb3af41fa75bada89bbcfa4b0feed9a0d6d4b19ed1ce1033b53c","15b330546e9784461058e5fd6e2346bf272140fa6f0cda34e193ae501d8b17b1","4d8ce72fd080bf9a46bdcc274bcbacccedd66d84e203966b197ac25a96932183","73327e6ae34e3f6591877fb75b451cf620cbbd76ee2b678213a9f793633cd0d3","3f1ba2f69944fa346789db7f60d53c9bec00032de0d797967978dea42e77b941","3f5df31539fee4816b97d4e45b4344fbdaf3ca59f6df941f8d780ee441e92cc1","50aaf44eb4d0e086af13729b3471a0a7dce95ea35ebd21c762ba26e203134b2e","3857c1773b8503c3ca45b7bc09ac89c3930c85ce93021054503f73d5d9101b5c","72702bd07fd6fb3ef64aadbcb909103aadfe71ee76e9fdeb11e0c92693cff6cb","f0dd6f7c9783637655478db7d7caf6becd41a79d54482aa59578ce88ab38e9bf",{"version":"cd756ccdabf433dd02b84d755383e489f14b3c1aede0477783aa04830fd5d695","affectsGlobalScope":true},"a4c88dbecdf8ee0c79f5b7c2bf31cd77e593f5d78384e2b674f67d754a549a9e","9cbdff04326da794ba008c0fc977ab062d1fe3fa2e9759654c72ffbe54b64a7c","aa60f8d20d36116fe05edaab24adee3c275209f71b65e272692cf99daf9489e1","150855f967a6490161d5aeed4cc4adf31fcb8f5dbe54b75799c12b8687fc9cc2","79576487ac18e047e8192fc582ff488ce375fe4df0cb028a17f831cf42b976f2","47ddb601df40bfa01cebdd06ee8b87d0b72aa1259a4ceba3ad3b5cf68130112a","6b6392704ddb3f50e647dbbb716782bdd0cf8ea9cc134aae256a26223e632b47","afc3ad2a50f7f4de908e26fcf467e09ab8528c0e90f91e602b4865d953839228","df90b0c6b1d81851364c4d97fa23b91a993482bcf4a7bed7c7a24aa41632d494","db34610570eed46b8b72bc662a91261200b8578af0ac02781ce7d9aca99bc683","11ee9ab699b4619d217c640d917ca198f58066a86bd58c2917197d62aa6601e0","cf9d589d9e73bf32c8e7a6cae6b4a1cf9bef39e5594072533fdce985581a6ddc","959544feb1ca2df29eec6c500f27ea10f4885df245ebd8418fb4b87914614383","6548ab4b57eb9d092471a04513091673345f2fd95d5b876f600402ea8d603ee0","2793e8c6a023d26f78d6777a6d7f20fae3a9a8169863d46d8d54c73071851232","d0f11e830aa1350a31d9c00a0197243e9711e4882947aef53a96c629f405cb10","6610b9f45f1f71d2b1fb67df49cbcabe3f9e668a1ccb7d8328a51407b259ffb3","abbcc437e0792ab2fe08797ceca1ec85a95ec413c51612313b18ab8e75f690f6","e29d76ef1183ac0edf94b4712b6e51730c447c7e773e75ceb44a720b0c9a9fd9","4ee6dc3424998eede9a2a9b114acaaf7969cdda67baf82ba2c9cf88a8eec0ab1","8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","25139d6a726e0e19d9fc4fa3197367b4a82ec34a08a5ecf23963e142c202c0f3","e3328bffc8eab74665a4fe9c59d6f12f4c8570c3d858497e241eb37efe17dfcf","29389551e426a46421134b55182d6fcf5b143670998bf81db2619c1228235392","c18f7e16982695bdd04e3e183a327d116185f77f1a37b9b2e849d7d93269cd74","2cfb37011989c21dc70b91d521a2d5a4e0f18507f5f536b5dfe504edb15916e8","bb5e02df7aaec7a4ea642639a9963b24b8d9fd6798351f07d8c58616942fbcbf","299a899cb4d061f5d83843ec453e936e9659b2c435746823f90c40eddaef4745","d5610c0fd12870f644b0f42c1bcc4fa2295ac3e3ca01916bdb42c3bdc4c80c36","2c56a8e249b1f45dbdf973100cd37fe2ea68709573cf1fdf2e3052c593be68d8","3553da417ee7b07e388b13bd12a70a1c03e65a6132ba5427fe68f5b362373e6f","612358502042d351c227ba779fdcf6d875d827e424930e60297c533524e50668","d2b5be376ef162aa0c24a826e7dd2d77671a045c085e16d1c1276db4bdccbac7","c4138d8dcccedaff6621e009cf0a54a7bed2a5ad4c509a3513bccc4f417ef939","ad8747fe978dff3e80f4b12b48d37cc8dff11b61d04c035aefbc982ce21201ce","b154f789fd65298e1ba6cbba6944ea892d564c95f3d3700ed85baf8f80748473","c660265aedd7c5b236e2017e53095cb98da66200eb0e8d023b5bf713c36494e8","0efc36bf5c0daca6217fec7063359ccdab8c3a23bb405d25340fae22cf72d74f","5abff0c87d4f9c89715107042d4c73b68ef7a128759f451c8a0fc450cbaaf660","5a03308fbd1af441065149a84c692931bebc7e7735afc23be8684f4e10d3aa06","c787bf4f8f0abbf815cfbd348be41046f2b8f270be24fe7aa8a8fcdd2b7df8c2","e7a5191c663a3228f30104961d548b372e51c5936c01ffc8eddd262bb98d7d7c","43fdc9abe6f8640fda4cdc55a1ee5f666d3fce554277043df925c383137ddf69","f0b09665c9d52de465687fbd3cfb65111d3ffc59ae00c6f42654150f3db05518","72f8c078d06cff690e24ff2b0e118a9de2833dcebf7c53e762dcb505ddf36a68","9705efb0fd901180de84ca4dd11d86f87fd73f99d6a5660a664c048a7487e385","f9b9d0950fdfb90f57e3f045fe73dce7fa6e7921b37622fc12e64fcd90afbd0f","e61b36e7fde608f8bb4b9c973d81556553a715eaef42a181a16ddd7a28da4ac7","03b8389b222af729eae0fb3c33366dcbb1f5a0102ce319bf1d7d5ee987e59fd0","2bf6be7c04db280fdd9b786764f8650c23f9f4d533791cb25a11b25314b76a55","dbb5fc7edd36bfba95cc4dd564e4458276ced30eed18bc05fbda948b3fda8686","c2b556c7cff0dabce2e31cb373ac61c14d8ebc35f1086dff30b39e9ec5357d0d","f958af01131076e8af55d28c4835a51063226ab488ca8738fdee38aeef7d0d33","9f3797b01e3d83d4e4b875699ae984f380ca86aa0a0c9df43ac5bba1cb1f8b7b","752b15ad1b34887adeaa838fc55f5d4ca399026afd266d4ed4db0e3db02eae4e","778331eaea1093451e50be9844bd2b6937c3bb81b0b1ee700624c9774ecfcf2b","0ca0dfc9f657d0822eca9530c7870b22a1d2a5fc48182bdd4d0e6e88e4ad9c35","5c746f034288e6842dd1589b169dcfcc16c5ce5abbd928889ab67aea4fe0b501","92ce6dbbcc135cffd09a58e19fef34bf351391bec92c40d849e4e9997d475769","99e77d092fed72b6b8578d00c7af004f76e98b30ba99f1947535eb4c04a51676","b5ef52a9f9083724decc5d060f0b34e3a480deed71c32d55ca16c214eb4cc928","5d3d7938b2d7d0a9f851276741327c2ae4c013e7eb420fc3f7caed3b79c8f37f","14df6b81e50a035e9e391558cf30a0420d03e2eb42c7db9c57f44b818e5d5179","f100912a3785eed4a3d29c12f5910b101af9353454de5ddba9b4d43456c56dd1","446439eacf81a163fd7dfc53b28f80deca3d13b250d67639739aa25aa4491090","98034cd285344125f7165a3bb68246d38ab35fabe7f6d6a7c8f80407d31f548d","06b4a23064991251512df4edc12341d5bc69a17b942da18372312d383c90eee7","0f898802705f9a534b537f1be6c57265080e0abd6993d935554c255e6d56cc1a","745efa7b6e27b7216cccede166a822b56acc41b10a8090966c8cf2c96239cb83","6ab2a6257ae7bb05559841100c786c845fe465a90be7b904db9096c2fb14696b","26958d6f77e6db2425ca65df0fbfaba439396ef7f4457f5643fc32e4b62568a6","5d697a4b315cc5bb3042ae869abffd10c3b0d7b182cda0e4c45d8819937e5796","89b040dec8fcfc1de98827e1f4d4977e6ff5d3302c6790e9f10b54b916e1c742","6ee58aa536dabb19b09bc036f1abe83feb51e13d63b23d30b2d0631a2de99b8f","8aceb205dcc6f814ad99635baf1e40b6e01d06d3fe27b72fd766c6d0b8c0c600","299567f84bfedd1468dca2755a829cb19e607a6811673788807dc8921e211bc9","795d9fb85aad92221504db74dd179b506bd189bba0c104426f7e7bb8a66ffee5","1311bc194e0a69fe61031e852c1c0b439e2a2a3d1d5e2d8ff795499b9f283459","4b7ce19369d7e7fae76720c2c6c7f671bf3fa0f7093edb864f1ac358ca7c456c","c972ef44deca1fa8fab465915ffa00f82e126aacf3dfc8979c03b1b066ce5bb6","30285a1011c6d6b52f3ba3abb0a984be8148c05cdefb8eb6eb562335a3991f35","e0de9f50e80fed1cc161b50e8e68dc056e38df75a4ef667a06b1922e372de169","6a8b31be08b212d1fc96de0ddd1ea49f32382ba712fea24c70bb56447f643f82","19ac6d624e4c18de4584db4bbdbc55387dbe3d19b3c134e50346bdf165658a17","54e3798c2801e8f3bc7a825d3d26c6a80ce763e19e6cb0b714594c430ef72332","70b8333214aadaccda8d38435911d3e3a686e503837dfda6b8c3f8c83e05729b","fe849e916564b8172f31a547395516668f3c122bfe017f82e7140d8dac402208","d42c6e985bdb10a2aaa3dae14d9b0d8589e74a7c2f9475bf543b855bb3c010ba","56c48fb5bb6316dfc27fbad065966b4ddbc38e9a0a1a5060d19b5da405ae7d6e","7091568b9a1b74b699ad09df6c130db712ed089d173a235e301a7a7ee0a4ca44","de33aa2a38affd9e71297ef7ec001a4525502878b09744308fb6518159f77d2d","57476e482c9b4e152bd23d0dc3c29375e48afee0de775674a3c1ea63cb4cf843","3ec4ecf6502ebdb1f3e24c712eb70160c606214ba2e71b4304b5a50fc2e4f293","83f7b6c1dc91deece32c3bee746a43f3616b7cc9f6510764bd53451f6712ff25","c23f2e8772304163fa7e4335be11f3dbdfd720d2209057566b7dfef746ef1862","2a26cb78d3de9708cd656787a663902270c9421ef89188286c3b7ec89b63bb15","e61fda2800677c210116c397dd85079a0956c87fd714826c08b25b10fdd56546","ef7bdfb4f157f9c9b9bd7f5766f0f8e07fac8e7482eec071673f3c9d08082982","d2f2ac1436cbb7c8d122cc7de96521345254e5b36591d9d064d9763de2a7b254","3cd2ba07285d01224f9595924dc7f760c7babb386a6eb825cb551f8d829fe6fa","3ae9770861c2ece5849778e9f15567d95b87df0165c0a5b1312181df19458a56","37b51656ff8302a4556e29c775f311eb9ad813948d2c527405cea041dba3baf3","00abf32ca3af92f8be9ecbc9b63090b4909a756317d791927a83cffd24e9c8ac","cd28efe88fac7a92f3f5cfc7dd3c764f0b31bdaaa061ff044de1639810d6a7da","8b2100d3ba68063b7baf5038f26eefe46543dcebf1e7dbaf46277f24307cefcb","131b7f32092aa78e12fcb2a6db7c71e17f85e076c0635ad8d991b80d10130c19","d1c84af1e6d5fa4a5f4badd45b03b67c9255a675df235a3ec25307a0f5524278","aa4d6dc9282133162a76109d99c5795583276c4fd27284f128d484acf12b0841","3355c4c572f076ad963d95f0e28075b8558e2ab492c84eb94f9e2c48f1c2368b","5638cfd48b0c56bc9ed0c779d53a40b92c9cd9c9d6312e3a21c52542d38094f3","827eb54656695635a6e25543f711f0fe86d1083e5e1c0e84f394ffc122bd3ad7","2309cee540edc190aa607149b673b437cb8807f4e8d921bf7f5a50e6aa8d609c","703509e96cc30dce834ef8188c958c69306473b8a7e5cb3a6f324cee05a1f7bb","900daf04dc607dc3858c0f976d6f9e17b829a07de58d62dc6f730eaf06986075","08e0ac95e650bd4c87145b6ab2257b70c06254bf76a0b9f8a7d60c51fb8ed6b8","4b57ec505a035491c692b89af2c6902c312ec22f8fa9b6dae3e93686659fb7e0","7d796672940d3b2d37f2edea4d7bcf4c7993966286006228cbc8fa35ac92871d","132fd53917ed7f55275faa52c35e4d4d41e9576fea231d12740b723df2bade93","de2ecf9b1d6f60338f7b59b6f593ef77af9abd0e70ba8f2942953d0c6e1850af","cf18e9d003f1d3d1d61a04eb2d1cff3e8a8cf9cd306d0532ea82700069f2fc42","393192a39f26f9247a74ecbaea6668972af8e9125c955d1798234dceca6010f7","27ca878cf70b3030e8403f51ce65949d364fa776d6dae3527f91635a40836672","178e2de7a8702742957ad24deaeddec84a48cd913b5d932b16afd2a707b3e416","a45ee7555d019a67fbe092898d1aef0b1d02a9f6679ab84461ff515b4460d706","29c188a2c660f99f1b4835022e011c4268d7af989d4b7dda33c0a69ca1a777f8","1ed0bf138e87912d741e28333b58cbf814ae863783b3b404d2454cbabb9c5fc0","3452ee7d8ef0b1bbd47b2a56924a1dc3c79dc84a19d212e9dc496f92e4943aa0","8c95f96ccd4be0674944077aec1e4f2cccd515ca06d4327562dd017250e7d3fc","6fe7571c8a80808224648046008d1366ba4e29206ac79ce4c56d6fab3350492b","a98be76d8c257aa9e316bdb305b8c4228f0cf904d4b70547fc2999f3f99b5a01","7419d99dfe020d543c8ee736ab7ec17127d6a2c61c40e5f245c6dbd3fa6eaea4","2495815b16258136f98d91e441f4462f9b694520af86bb8c8373724cdc410096","a64568c16a5821575de4f6280ba1ea4686a1ceecd649fa90ba957c8b1b007013","ac46f284c80582f7c1284eef93f2d1c80add2d3b0e8a4076d6ca3db58d3af747","dee4dbaef83bb1061a44f39a91a59300d3dc02528eb57f748222235dd8e02159","a39c32b055d2e6103e5c49b9aed2d7bb5b06571c98fc31105264d280431bdbd7","618ebb93311695a13844118cdc9a7314dd3a2c6f35092d87f76828cac555ddc9","d36c3d116ce59a3f072c0014f0c020c76e916ba906066ddc4f193f546a43bceb","9bed8447acaa89be63540ec500b165442fcb0de020015175b5a5c66d42a61c4a","f128a2d1209d243ba2f7755c2fc313be2c7569fa0d9b4dc5cc60714fb0cc6634","a17e6861b709149f29a2bd896cee94526df2f06b24a2b60614b56649b5e9aabe","9c79ace686f720f4dd833740f7190e12cdce363362c982c164745527a412ef40","439850ca5075c6db55487b2c7fb27a6051fecbf180eee0809b67bb2783a89813","75d48857bc4216880443a24d985071262bb8b89a9952c77fd430cb0caa21f9bf","33e40cf77499b3d9712db82e15683373925e85817dbe82a24ee0ee6e44bffb70","d5bbd453310990e851908183fbbef9e6e2db8e0c86d97b42b723fd5238f71c81","95e76bed30f6e993e1fcc1b90a4675682e4800ae43403547a775d6e3c7ab2b0f","8b206b995edc6dd849b85c1c56531b9780e3ba75302fd02a2d173f008028707e","97040b190f0daa10cf9a15e51a2fac66b26ddefd7b65998bd6027d1dd67647b7","877c25dfae100e555014e45d1d80364496a0c876201e5dea91a0fd0a6a4ff765","d53f9f96afd41359edeb2d5ad98559f3bfad261391d5aef95320fefb0c6a8742","23d98226adf3be74e1f0470f85e7fd154cd7aa979d60b43190a7437f0d0426eb","639f9321a98b734242a3573764d7f1de5369b0b0b10c768ae37639e8bda5dd03","a42c39d8b7d1b1eccb69c7919ea60dcc2670ea672a0af90b70a730974ec0e9fb","dc5fe5f6b39c3fdfaeba333bcd5f0cc98bb3068797a4d7010f585366f549ddf7","4a3ab8cb278bfd1f18f24cc45a02188b63afa6aef50035df6d79c4638f24059a","e724c9ce92f2a8a31ed260764c5455852a13d292e2a31d26acc6840ec0e83208","40220ba1b091aff0cb20df5467202b62af561b09fcf3b24c22a60066d46f9e62","30abf588759f9e828a94f0c7f031eae094bb668c6dd4d902fa296779267c05c5","bd875d031474860131eadb42300aa57a71527bbb2b239d5b31ab6a9e352c84f0","773bf9af93b5027de9b5b4c779d5cda35f0eb92c7f43a97f2ef3ca081495a191","617f2b4f5115969c7b0f225d4962e6bec1cec7e5c687d84370eba4931b7dd047","59625b1fcc91f2686751fd5b623126f434d7b405bd8d866a555963ce2ac69846","5e0dc1bd24b45c46f2188d2f7f4b67f311610c72b706f963c5bf04c2e1fcc35d","fc69ffd599d3e525aba38f80c7cc2ecd187dbf148287364c75f199c8294a00e6","2ad138be6972de52ed966e6402aa6403af79e9f183486e0a725ffa075a0555fb","480274a4f75a7b3bd5c697a55e1905887b62a928592c0db3c282525fb235ba70","967fb6e86b55db228ab50c81f85f39d6a23a0c15bcfa6e19d255e0952d33a65a","c39e7d32dddfcdaa93b18b99fa430ebb1d6ba366459563d400add22f92e3644b","e3932de252bbe43132ad3226865b2a376ad945dbc1d767540c01b7bddc6477c2","b2f52f3cbd863dc4e690614b5cddbf412dea435d0de099db6d8adfd3cbefcd65","557c93b35f3b58e6844a9b8817559da1e0641f7f08f918e3cd1a8efee126746f","80ad2ae93d57dadac5e377ec6743df5e0211ea30bafd4b648c52366af057bb2b","07f90213b5800a0b43a6d6f309517dcca5afc6ffeb4bed396878a29fc5d6ceb0","bb0e637020f81cb40d16f202c3a783f0e269e29547fb84ca9f187a5ea8556965","462da802b50ac0d94a3c8f7f58a6a0aa08108bfc1394449ea56f1e0f63f5132e","2ccea88888048bbfcacbc9531a5596ea48a3e7dcd0a25f531a81bb717903ba4f","b7eece07762a9a944f097ee05d6f6b642b1e2dd87e6fc1b09600d881e5475377","1916218868966583a3c9f18501ee78929cab8450ebb8076ebd609873c258154d","98ca5ae10ab02fe747a7a53138f43525e0129aa1107892ea4e1fe9c99575809c","9760678d20c9faa0d0e1269806bce578bb76598a4a188a4d3987171263be20c5","21f706150e32f03ecd1714d7a7ac55ce3caadc7c7a2a960ba57cc5d39ad84c9d","6954ec87361b77bb8895426909fecfd154e3fd72a2b82f681c8bb15bc46f2389","da1963f37d566ff9f71bf8ca5c628656bae02fc9509050041547e9c7063cc58f","57e4bed825036f7f1328505bc512af492f28b1b57a48f1ff9b6d90b930041a52","3ef0957915b7719ac58153eaea6ce810ff8688276e570f8938455f3ec7930df7","05e0ad043fdd4e2d4874a97bd716174af64d63e43851c09830c00e819a80d395","2dff0ed1eb2046fbdbc2c13914117e1ff1112e217f90542ea5e7f41e39f0393e","a0ba1e2711c2520189ed980225e7a429b0706a1eabf9113e53f0e72550a1b23d","169b66aee819a4b165c397b832b31691f0be8d35cf8f2ec6364c23ee727b20b8","badb4cfbfc6eca3a038be22c76297bec0b5c1478d8b73d60e8b50725b7dcc15c","21e7e0eddddc112f2b891d1066eac74680291db768d3ef9b908965935380ab98","489e195150979dc291520e6f3289f055516cf342f314931c6b4553aebf2859bb","516efe800aaa0b7504b71f2d7e7e9bed5f28eb6c9c739bfdf237f09c7addea46","10ae729013e6620dc937df5dd7077c34e29ad313a28aa75cec39957640cdc8b0","ac5f95dee5e4787fa7c68a81a052cdfa0e03adec8331d3276389384df36cb849","0aaa321f1f662ec931e55c85867d316d8af16b59337111e22901516a0e1caacb","fab58e600970e66547644a44bc9918e3223aa2cbd9e8763cec004b2cfb48827e","a120dfb4736e6ec4c78f1bff5ff7f977d346152e6b7020659ee1ce4717f6f66f","9eda7b58498bed72dd98ebf1d6f8dd3bf5df5004b2f91c610093bf48f970c615","8e7adb22c0adecf7464861fc58ae3fc617b41ffbd70c97aa8493dc0966a82273","755f3cd1d9c1b564cff090e3b0e29200ae55690a91b87cb9e7a64c2dbeb314d3","d6bb7e0a6877b7856c183bff13d09dd9ae599ea43c6f6b33d3d5f72a830ed460","f1b51ae93c762d7c43f559933cd4842dd870367e8d92e90704ffa685dd5b29a3","3f450762fd7c34ed545e738abccb0af6a703572a10521643cf8fc88e3724c99c","bf5d041f2440b4a9391e2b5eb3b8d94cbf1e3b8ff4703b6539d4e65e758c8f37","8516469eb90e723b0eb03df1be098f7e6a4709f6f48fd4532868d20a0a934f6e","d60e9ab369a72d234aac49adbe2900d8ef1408a6ea4db552cf2a48c9d8d6a1bc","0ebb4698803f01e2e7df6acce572fff068f4a20c47221721dafd70a27e372831","03460a54d0e0481d1e11097f66ad43f054bc95efdafe5f81bbc7a82be181af75","ded24ddc7157689a5aa14bd651272ab8cd6e7812da2196a65d8c5e63131cfb23","2cea9689efa8591732096235abe7f084fc29c92badd5b0897a5e876b77e71887","4ed4e504126014fee13aaef5e3fc140f2ff7031ff3a8b5386717905820ea2d09","00e77e0bf106bc1e4f303ab02724df5173506d44acb6c22b4f582a88f22c3250","30d2170e1a718b5035611af55e3618b4ba8f42f0749bb52ee593da6082c4e2ce","568c86c9edf716ae08cd3c8ca61647a3eb43ff52a9aeb7c972f7be62cd35b797","a3b8b6be7620897d1e481e8650c980a210a138fceb6e710eaf95fd9dd0dfe94a","12c89d0e32758c120a569045f21cf5b77244f86792611ced8de7f86b37e77781","14bd47270e654c8eb3b1489fa8c095912ee62a0a29bb92743393203722347c53","cc8b411aec64e03abfc3936a397025c781adb89942ec2fcc66e2a353f93ce677","db5624ecf400ed47648e72353a0ebefd3293d2e6295834a3f013c548ecbd0edf","92cb686a9ca5eb5dd7d5d8d43a3707194c1e91ea07a027b3bcb60b6011b24632","da3ab7396ab4fe390f01091bd0d4c4a4e1e2a15a46d47446d6fb7194897d0f6c","66bbae6120d307ec2021ebd2241b8ad23f832b663e13363ca8b4c8dbc131a4e6","fb14266ae4070bd16db6b071e98887452bc359695c40742e38515a89dbc80a63","4a24d83c0d8f489465c4d38ed9fd87121c8a2cf50c47efe09c2eca93d39fa908","c052e32b9de53cd2596f196a0901801961bd7a31be9fac4ac2f117e4103e3a07","b15cdbb45919bc3b8e6b6f962d65382e85061d70bc26a968604f3dce4ad3a891","d6b58d955981bc1742501b792f1ab9f4cba0c4611f28dcf1c99376c1c33c9f9c","f0b9f6d5db82c3d1679f71b187c4451dbc2875ba734ce416a4804ad47390970a","a5c38939c3e22954a7166d80ab931ac6757283737b000f1e6dc924c6f4402b88","31a863da9da2a3edec16665695bdbc3134e853195f82dafec58e98c8e1bb3119","a00417f73bbba413d1345dd77252ede0bd0c957e37a9cadc9abb4c34cbd0eac1","90d1ad8d2983cb003d6f237b41c56a8f252f72071bbc53576e02b3c96d7ea47a","f3815045e126ec1b9d224782805a915ae01876a1c7d1eb9b3e320ffadbd63535","d07557f21b2ad690bfe37864aa28090bd7d01c7152b77938d92d97c8419c7144","b843ea5227a9873512aa1226b546a7e52ea5e922b89461f8b202a2f2a3f0b013","64b4d440f905da272e0568224ef8d62c5cd730755c6d453043f2e606e060ec5a","d6b58d955981bc1742501b792f1ab9f4cba0c4611f28dcf1c99376c1c33c9f9c","f0b9f6d5db82c3d1679f71b187c4451dbc2875ba734ce416a4804ad47390970a","a5c38939c3e22954a7166d80ab931ac6757283737b000f1e6dc924c6f4402b88","31a863da9da2a3edec16665695bdbc3134e853195f82dafec58e98c8e1bb3119","c0e03327bc548757709a7e2ca3063ca8b46227b5e13cd981ca3483035ef5ac44","b8442e9db28157344d1bc5d8a5a256f1692de213f0c0ddeb84359834015a008c","458111fc89d11d2151277c822dfdc1a28fa5b6b2493cf942e37d4cd0a6ee5f22","da2b6356b84a40111aaecb18304ea4e4fcb43d70efb1c13ca7d7a906445ee0d3","187119ff4f9553676a884e296089e131e8cc01691c546273b1d0089c3533ce42","febf0b2de54781102b00f61653b21377390a048fbf5262718c91860d11ff34a6","6f294731b495c65ecf46a5694f0082954b961cf05463bea823f8014098eaffa0","0aaef8cded245bf5036a7a40b65622dd6c4da71f7a35343112edbe112b348a1e","00baffbe8a2f2e4875367479489b5d43b5fc1429ecb4a4cc98cfc3009095f52a","68a0d0c508e1b6d8d23a519a8a0a3303dc5baa4849ca049f21e5bad41945e3fc","3c92b6dfd43cc1c2485d9eba5ff0b74a19bb8725b692773ef1d66dac48cda4bd","b03afe4bec768ae333582915146f48b161e567a81b5ebc31c4d78af089770ac9","df996e25faa505f85aeb294d15ebe61b399cf1d1e49959cdfaf2cc0815c203f9","4f6a12044ee6f458db11964153830abbc499e73d065c51c329ec97407f4b13dd",{"version":"99e8bb8d262bece129ac203f0c7436a07771e9cf5ba06a308d1b16993606eaf2","signature":"8705a9680ed4afb15edbd7bb9ee24af33060d1165117f293559f3073bf8d0101"},"ebf6e19cb84d78da20d022a95f05e8aef12e56f816a1ee12835a4da40d7b14cf","589357c2f88f1188a0dfc48c4c4cf4d22fac9f654805df5f2789a01b5616b74f","6abe62ec5b9b6a747c1a7687d58ff179cdfb61adee717b6e4882120f7da4399f","5c1301f550be26133f4fd34eadf38815db096ecaf9b75948b444a063097f496d",{"version":"26e64fa5fc9c7fce9daf4131f396fb5012dbdd92fb2e2bcda5aa083a76d18888","signature":"cdca22d444beb7cbe168d11a666b994be4b19c5ed7df1856612ac4dd7c2242fe"},{"version":"34ef3dd636b7074beec81346987a81ac245e1cfd75adf0babc68e6cb6c572ca3","signature":"82065c62b6a8089452cb40191a55299b2d0718ddce833446faa6c01f48f05b29"},{"version":"c1eb1aa5e32fd31d4564bffb458942d8caf500d86388c811cbb853c274e4773a","signature":"a7fe41f597b2631d3fb439d9b3ee32d1606c651a45ce2fa0d170a2614e68d280"},{"version":"327fd9ca522780f73a64e32e400a6c5bcdd89a5e706314d57ff1611bf1a99a0d","signature":"70b3082385b926b4bb0dbcef0b2f444c4f807d312546f27ee248d50b0dfa5877"},{"version":"3b1ea19c2b95501c5d8e87fe4c8044d204c4402a8b48f282bd348f973355f3c5","signature":"01b86f9481ddaf74b65f12e90ae2d5bedbc0e67e64e8cb273c7a1907cc66dbec"},{"version":"897a42f20db3ee955b1cc64506c040b0b1dcebe45d9ba3147e133d110f487f6e","signature":"3089238aed154b07430dd80de65df3115d268f21f1afcd8568a58d65c7827c5f"},{"version":"2d41bac312ef892971b2344a102feb99985e87f79edc18ed2c43ece97703fb91","signature":"2642375958909546f682d51f9c3682f553ae5f919f7b4a77d49262c200bca248"},{"version":"db3db9885deb334e6606785a0bfe7aecdcae172d36a6b4bd55958c756b92ac6c","signature":"79cdba32abf1fd279e588363d3048cb4b3d537a81530d32079cea1df22d66f93"},"1fcb8b15db812281d69a3090d488903f9e93033004aef9d8889ca3ad0753a96f","bdf5a95eb0a2dd1d39805bdf51b46ba012bb9b92b2ddaae16219595bba7678a5","9f794a0e8550a03baff865a3961cc22afbd85bc4ba9672bdda036971928f85f4","66a697d1e4cdbf25cdce4644a8085a8563041fa8c7731d4d9f5e8f22e66ba72c","a0c8e17f4d1ea2704c62d7349bc3b8d9a12e3761b5960cb44144d3f0333b3fcb","3471c0df3d0391e1dffe6e8bf150294531b2b71a2afa5f2b86e52bf84a5db60a","5d4df4de055eddf3187094f938a640f8d96e4c551a47d6686596fdb6ba4c3014","8bc2cad630da1033c1fd8d7df2bffb18af0da6113bd086a8bbec04a2471a1e00","a1059d1bbc8ad46bfe668b8450e7e8002887c4ab987bdb96d6108d8023f8bb8f","5134885e9648e2c6745f8aa1c3e7f5ab3b3617258b3d81ca02de6655ede3d74e","4f1ae3f24125216cf07c5211a3f00d2bb4782d7cc76c0681603f8249f9232ff0","d3fb92a5640f83f7844d60b35317a0f95c27e3658a749d76d218c461ad091668","d1f8bfcd91b284657ef8187c55ace7db91a3c43e642c3f14e54364154932f7e4","f54c92bfcae54f360fe79514746efce4870e4ddabc064e95d406bba291e9f672","175fd7186fa6a70f9db9b270a04a503cae23cf01cb77e3905bac115c38424cf7","c993f7ed1b8e1023c1f2ee5b262dbc3b70b27475674e40a53a58591f9972dacc","c914014ab7c7001178663f29d31a495398234a41219af61f26d7e8e91b46af96","277afd6ab6ec72889e2988e0ddd7d138c1f512e68a1fa4e90eedfd71e2097a51","c0908f85f2b645d375127a3b53a17a65f782e17962d5c1eb68f08b1188acbf15","3fadac5d409cc2f27b1d2f4e7568600f02840205f301c9ae7a3068b46476438b","da6aae64ad559286830fd44c81e3d33303348f184af7db4fde8dd99ae9749407","3633f87c97d359cb55fa7bf0668fb2be8a23342951af6ec2d06e6d0cf7409371","cc3a5427d44fc77ff25e80b3edee4650a51f83de761faf5e633994ecf1ab1b44","b350eda75c6e47299b36002b31d5b220c405c21c365e708989829db013fadbb4","f421882756b6714834ae4687ab1aeadf344a1cc45437d2edffbac020ff3801c1","1d61d6ad832dabafbf63b86c5a79d704f2c8763ada9318e135b17a3cb2d09b32","e5cef5de3e5ad3436d414d20743231e284733b9cf4375dc79eff4fcca4282f99","e624419ba84e33e661e89a28083119ca41f6953dba09a4f82b660684087afe6d","942be430bd0feaced2e3e598273b17e50ea565ec9dac840b580b0b99e1a3cd5c","73350006cec5a0c6b71d53b0b0ddbfb82be96752a9c4e3c904c59e633bc9485e","a7df5c2e9594966c7e0d4a763b13ed5727506d892669df5f7bc9826f539c1d35","258cc5cd6891f6bcbaccefd953997038844e7f65d582cac987ffabf7181bcd4c","00a6db28fc4df6ddf10adbe630d9df620ec13af19039c1869653e60dafa739d2","649324d5abb5464aabe35d86cd0eef16562df811f0971481cee664afa5acbc88",{"version":"628749b6edfc907c32583a77f7dde111642dbfc13265fa566e9a8fa47f224b51","signature":"495944b274165419ec08446dbd612d6276e2c12b92caa1f1e6c645cbc044ef25"},{"version":"e2f7d4348da1a42007547574ec71504de5e9df04d270bcc4c672bec1068257e4","signature":"0d7e153773886e59a74ffe1fac08bef805541411de160b9f3af36f8a6a3c6022"},{"version":"70fa251413c8e1926804d27e8aa01f96bf56141270e8adaeedfeaf0cc7147cef","signature":"2e85c128d27849ff4bd436f75d32d8a64d9013d420f09c82c6eae63cb7131020"},{"version":"334a6eff67fdb6feabbe5a612552a0714c424ccd07abbb096672085e7d43fb4a","signature":"19756a360a54eda2a10138b94b37a87519fd1a27c678a1b82187295e40bbfacd"},{"version":"722e48bdd1c494feabfb081d7d582d4554276abacce92f69128511918c125273","signature":"b195f1ad5886c1600c53bc7296210f9ded9a9a673e01988eecf9f20f48a4d9d5"},{"version":"1b5f109f8e1b74f648bf19b878188928678f443c2b2a21db0861f57d0715ef69","signature":"55310e6719d6bd9462e76cbba6a582712b30a85ee4949b8d98e14e0f46738e78"},{"version":"d184310a8c121c1ed754995dc55f8ca212bb1ef94979f99423dcdc48569b3c51","signature":"99ec28bacd04a3185d90660fe18bae48f33cbb1d50c73c64cae98e67f7c0ca01"},{"version":"48d475a0c6f91f62a89b128923cdec08f1f30a12df0068493f0d9b2774125b01","signature":"6a90b1b75bb0eb776ae223adc1f3f1cc343abf3e68df619933a3248910061290"},{"version":"e581d928f182594fe6aa7c0dd2e0ce02fe65fb53b7d40a59af9c2f171eee6428","signature":"1ac721bca31657133deb33e2ae005d557e8e6e0aa9a466142a2b0388e2e2638c"},{"version":"f18e14371215da28d2375c023017adcbd420314020f2a4ca4e9d9369ca80c1f4","signature":"0aeb9a7ce850134709dee9ecb63c1883e387eb70f960e0510100f4b2bb70caa4"},{"version":"bcc7e1fd0b70240f11846f0c5a284be69834446899b64477371cee7aaca38965","signature":"bab97a4f0736f1c1cd0546f79f993ecf30b34404cf4479a4f39068915880cb1c"},{"version":"6720778d4192df7ececcfd9dfebed8a006c9c44f88fe8b74880ab3ba7e14cce4","signature":"121c82998e23aa414d41a2f08e108074760318a1c11a2a5183b88b0d9be4ef60"},{"version":"e3fe28954899e21bf8a7db496cb4b90313e826bb5ae938d84bc73c3bdaa31cc9","signature":"4e1f22dbfc0754b698f1e291c7c92bf1220834bd5620207084236399cfd02e2d"},{"version":"7f2a2cdf8eecbe353d449055d91c6ee619f90ca3b3a49ba5a44563c44aab5d1a","signature":"8e6165fa13e0d2f40e2403ab20b72804d02c663709a3f7383a320050e893fe8b"},{"version":"a02cb9d0a7363cbbce45fa86bbd7d64615811e30f2a7c47a2718fcf53f20eae7","signature":"9af2721670eb3402e476cd827256d4af7ab1d6db57f1615cbef18c75164df9e5"},"14c94f7888c75007a94132f03caef0f6b58bcb136c2994213fd2d3b99f3d7f85","4695042a55a75a6c62dc57f2efe60ef3c7bbe19adedb5081f6e51dd664bbc3f7","b006ad8d854471e7a270bd8918508090961bdc1cfe77ed51f13f471fe682acac","310901df1081433ff7c3b7918496cabb92ded208b04294d3d2bd35acae2de836","c8646410cd2a6bf05eb7e7a51c881776410d07fd5d8f75092a2c815c9c6fda52",{"version":"127604bb56d364ecc35cbb4927ba7c53f552353fc7913b07a4f5cc957210aabd","signature":"973a1e0a155ab26d66226ff9d64a36cf61227e9240b21cabdc67df29847a6599"},{"version":"dcea5769c8b69d7b7a5ee6ffd4d22260e47d53d22990e91d504cbdc0c0120c14","signature":"16c51743932253da5b661b0a5068eb1423a6f020f62e6783ce8ac5259cff10f2"},{"version":"67be5e00299e02d108b294758dcc0218da9f2a2823dea61d708ddbe705771ae5","signature":"05fe3dec4dc02961a8959758da54c6ff9d32a232183041163d4d52cc6bf39015"},{"version":"e2e5ebf01c7004f157b8c750fdddb9f227fbf3119a87297e3a014db04c3f0887","signature":"fc6fe9c667e291d0bbdc904c921d2c1d385175f8c135d9e549298c96265acaec"},{"version":"6b0da45d7a1027dd4a9b14ac009b018761e8851c84a9e54ecc1be9086f0516c6","signature":"38fd30580198d072da98f6dbcb7535f47359ca91ffe57e3b9bfd1961a3b209ab"},{"version":"b75a82fbc994a947805538c6652361c50c70f121e173c9ae62b190b8936790e0","signature":"0e92b9a9c01325fa2e1bc7574a0ff68328f69f8db609be2156a4c3da5ce493df"},{"version":"4c408d170f00539f8957a9cfce1d7f3e4a2d36651dbf4b16337a7af5c568d7e5","signature":"a0c04e7f7ac63b60e113ff0a7ad4fbf9214babb1db0572641709a5859710e27c"},"4489c6a9fde8934733aa7df6f7911461ee6e9e4ad092736bd416f6b2cc20b2c6","2c8e55457aaf4902941dfdba4061935922e8ee6e120539c9801cd7b400fae050","8041cfce439ff29d339742389de04c136e3029d6b1817f07b2d7fcbfb7534990","670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","9d38964b57191567a14b396422c87488cecd48f405c642daa734159875ee81d9","069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9",{"version":"64d4b35c5456adf258d2cf56c341e203a073253f229ef3208fc0d5020253b241","affectsGlobalScope":true},"ee7d8894904b465b072be0d2e4b45cf6b887cdba16a467645c4e200982ece7ea","f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","bc3cba7b0af2d52e7425299aee518db479d44004eff6fbbd206d1ee7e5ec3fb5","afe73051ff6a03a9565cbd8ebb0e956ee3df5e913ad5c1ded64218aabfa3dcb5","035a5df183489c2e22f3cf59fc1ed2b043d27f357eecc0eb8d8e840059d44245","a4809f4d92317535e6b22b01019437030077a76fec1d93b9881c9ed4738fcc54","5f53fa0bd22096d2a78533f94e02c899143b8f0f9891a46965294ee8b91a9434","0d14fa22c41fdc7277e6f71473b20ebc07f40f00e38875142335d5b63cdfc9d2","d8aab31ba8e618cc3eea10b0945de81cb93b7e8150a013a482332263b9305322","462bccdf75fcafc1ae8c30400c9425e1a4681db5d605d1a0edb4f990a54d8094","5923d8facbac6ecf7c84739a5c701a57af94a6f6648d6229a6c768cf28f0f8cb","7adecb2c3238794c378d336a8182d4c3dd2c4fa6fa1785e2797a3db550edea62","dc12dc0e5aa06f4e1a7692149b78f89116af823b9e1f1e4eae140cd3e0e674e6","1bfc6565b90c8771615cd8cfcf9b36efc0275e5e83ac7d9181307e96eb495161","8a8a96898906f065f296665e411f51010b51372fa260d5373bf9f64356703190","7f82ef88bdb67d9a850dd1c7cd2d690f33e0f0acd208e3c9eba086f3670d4f73",{"version":"ccfd8774cd9b929f63ff7dcf657977eb0652e3547f1fcac1b3a1dc5db22d4d58","affectsGlobalScope":true},"d92dc90fecd2552db74d8dc3c6fb4db9145b2aa0efe2c127236ba035969068d4","96d14f21b7652903852eef49379d04dbda28c16ed36468f8c9fa08f7c14c9538","8841e2aa774b89bd23302dede20663306dc1b9902431ac64b24be8b8d0e3f649","916be7d770b0ae0406be9486ac12eb9825f21514961dd050594c4b250617d5a8","254d9fb8c872d73d34594be8a200fd7311dbfa10a4116bfc465fba408052f2b3","d88a5e779faf033be3d52142a04fbe1cb96009868e3bbdd296b2bc6c59e06c0e","d8f7109e14f20eb735225a62fd3f8366da1a8349e90331cdad57f4b04caf6c5a","cf3d384d082b933d987c4e2fe7bfb8710adfd9dc8155190056ed6695a25a559e","9871b7ee672bc16c78833bdab3052615834b08375cb144e4d2cba74473f4a589","c863198dae89420f3c552b5a03da6ed6d0acfa3807a64772b895db624b0de707","8b03a5e327d7db67112ebbc93b4f744133eda2c1743dbb0a990c61a8007823ef","86c73f2ee1752bac8eeeece234fd05dfcf0637a4fbd8032e4f5f43102faa8eec","42fad1f540271e35ca37cecda12c4ce2eef27f0f5cf0f8dd761d723c744d3159","ff3743a5de32bee10906aff63d1de726f6a7fd6ee2da4b8229054dfa69de2c34","83acd370f7f84f203e71ebba33ba61b7f1291ca027d7f9a662c6307d74e4ac22","1445cec898f90bdd18b2949b9590b3c012f5b7e1804e6e329fb0fe053946d5ec","0e5318ec2275d8da858b541920d9306650ae6ac8012f0e872fe66eb50321a669","cf530297c3fb3a92ec9591dd4fa229d58b5981e45fe6702a0bd2bea53a5e59be","c1f6f7d08d42148ddfe164d36d7aba91f467dbcb3caa715966ff95f55048b3a4","f4e9bf9103191ef3b3612d3ec0044ca4044ca5be27711fe648ada06fad4bcc85","0c1ee27b8f6a00097c2d6d91a21ee4d096ab52c1e28350f6362542b55380059a","7677d5b0db9e020d3017720f853ba18f415219fb3a9597343b1b1012cfd699f7","bc1c6bc119c1784b1a2be6d9c47addec0d83ef0d52c8fbe1f14a51b4dfffc675","52cf2ce99c2a23de70225e252e9822a22b4e0adb82643ab0b710858810e00bf1","770625067bb27a20b9826255a8d47b6b5b0a2d3dfcbd21f89904c731f671ba77","d1ed6765f4d7906a05968fb5cd6d1db8afa14dbe512a4884e8ea5c0f5e142c80","799c0f1b07c092626cf1efd71d459997635911bb5f7fc1196efe449bba87e965","2a184e4462b9914a30b1b5c41cf80c6d3428f17b20d3afb711fff3f0644001fd","9eabde32a3aa5d80de34af2c2206cdc3ee094c6504a8d0c2d6d20c7c179503cc","397c8051b6cfcb48aa22656f0faca2553c5f56187262135162ee79d2b2f6c966","a8ead142e0c87dcd5dc130eba1f8eeed506b08952d905c47621dc2f583b1bff9","a02f10ea5f73130efca046429254a4e3c06b5475baecc8f7b99a0014731be8b3","c2576a4083232b0e2d9bd06875dd43d371dee2e090325a9eac0133fd5650c1cb","4c9a0564bb317349de6a24eb4efea8bb79898fa72ad63a1809165f5bd42970dd","f40ac11d8859092d20f953aae14ba967282c3bb056431a37fced1866ec7a2681","cc11e9e79d4746cc59e0e17473a59d6f104692fd0eeea1bdb2e206eabed83b03","b444a410d34fb5e98aa5ee2b381362044f4884652e8bc8a11c8fe14bbd85518e","c35808c1f5e16d2c571aa65067e3cb95afeff843b259ecfa2fc107a9519b5392","14d5dc055143e941c8743c6a21fa459f961cbc3deedf1bfe47b11587ca4b3ef5","a3ad4e1fc542751005267d50a6298e6765928c0c3a8dce1572f2ba6ca518661c","f237e7c97a3a89f4591afd49ecb3bd8d14f51a1c4adc8fcae3430febedff5eb6","3ffdfbec93b7aed71082af62b8c3e0cc71261cc68d796665faa1e91604fbae8f","662201f943ed45b1ad600d03a90dffe20841e725203ced8b708c91fcd7f9379a","c9ef74c64ed051ea5b958621e7fb853fe3b56e8787c1587aefc6ea988b3c7e79","2462ccfac5f3375794b861abaa81da380f1bbd9401de59ffa43119a0b644253d","34baf65cfee92f110d6653322e2120c2d368ee64b3c7981dff08ed105c4f19b0","7d8ddf0f021c53099e34ee831a06c394d50371816caa98684812f089b4c6b3d4","7d2a0ba1297be385a89b5515b88cd31b4a1eeef5236f710166dc1b36b1741e1b","9d92b037978bb9525bc4b673ebddd443277542e010c0aef019c03a170ccdaa73","ab82804a14454734010dcdcd43f564ff7b0389bee4c5692eec76ff5b30d4cf66","bae8d023ef6b23df7da26f51cea44321f95817c190342a36882e93b80d07a960","ae271d475b632ce7b03fea6d9cf6da72439e57a109672671cbc79f54e1386938"],"options":{"composite":true,"declaration":true,"declarationMap":true,"emitDeclarationOnly":true,"esModuleInterop":true,"inlineSources":true,"module":1,"outDir":"./types","rootDir":"../src","sourceMap":true,"strict":true,"target":7},"fileIdsList":[[666],[72,108,109,110,125],[109,110,126,127],[108,109],[108,125,128,131],[108,128,131,132],[129,130,131,133,134],[108,131],[108,125,128,129,130,133],[108,116],[108],[72,108],[60,108],[112,113,114,115,116,117,118,119,120,121,122,123,124],[108,114,115],[108,114,116],[605,609,610],[605,608],[608],[609,611,613],[605,608,609,610,611,612],[605,608,612,616,617,618],[605,608,612,619],[605],[605,606],[606,607],[605,608,614,617,619,620],[615],[616,618,622,625,626],[616,618,626],[108,608,612,616,617,619,622],[616,626],[616,619,623],[608,617,619],[616,619,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637],[616,624],[108,624],[605,612,616,617,618,619,620,623],[616,618,622,624],[616,623,624],[108,135,392,393],[392],[393,394],[108,387],[387,388,389,390,391],[108,359,366,367],[108,359,366,367,387],[108,359,366,367,371],[108,359,366,367,368,370,371],[108,359,366,367,369],[108,359,366,367,372,373,375,376],[365,387],[357,366,367,372,373],[359,365,366],[108,359,366,367,372],[108,359,366,367,370],[108,359,366,367,383],[108,359,366,367,384],[111,356,359,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386],[357],[357,358],[72,108,392,395,401],[395,402],[402,403],[216],[216,544,545],[545,546,547],[249,258,259,262],[249,258,261],[249,258,260,262],[250,253,254,256],[250,251,252],[253,254,256,257],[250,251,255],[261,267],[249,258,261,267],[258,261,267],[258,261,263,264,265,266],[249,258,259,260,261,262,267],[249,258],[250],[144,167,193],[167,197,214],[167,214,215,234],[144,167],[144],[189,190,191,192,194,195,196],[167,189,190,191,192,194,195],[198],[201],[144,193],[202,203,204],[197],[193,197,199,200,205,206,213,215,235,236,354],[167,200,205],[208],[207,209,210,211,212],[144,167,193,197],[167,206,353],[138,144],[654,655,656,657],[548,567],[568],[560],[562],[560,561,562,563,564,565,566],[560,562],[108,228,424],[108,228,425],[425],[396],[108,228,396],[396,397,398,399,400],[108,228],[228,427],[228,428],[228,427,428],[427,428,429,430,431,432,433,434,435,436],[61,108,228,427,428],[105,108,228,427,428],[167,216,223,224],[225],[108,167,225,228,229],[108,167,216,223,225,228],[229],[224,225,226,229,230,231,232,233],[108,226,228,231],[224,231],[167,223],[167,237],[237,238],[237,238,239,240],[167],[188,353,475,492,493,506,531],[529],[167,504,519,527,528,530],[188,353,455,517],[518],[108,223,228,426,437,492,493,494,506],[167,188,492,506],[167,437],[437,495],[497],[494,495,496,498,501,503],[495,499,504],[500],[437,495,496],[495,496],[502],[167,184,188,353,462,475,485,492,493,504,506,509,511,519,521,524],[509,524,525,526],[492,506],[505,506,507,508],[492,506,507],[167,492,505,506],[167,492,506],[522,523],[167,188,485,522],[167,353,485],[520],[167,353,475,492,493,506,527],[144,167,484],[108,167,242],[167,350],[319],[167,242,319,347,350,351,352],[108,167,241,242],[243,244,245,246,348,349],[138,144,347],[138,144,245],[277],[277,291],[277,278,293,295,296],[277,291,294],[277,283],[277,282,284,285],[277,282,286],[282,283,284,285,286,287],[289,290],[278,279,280,281,288,291,292,293,294,295,296,297,298],[277,299,300,301,302],[144,277,299,350],[334],[347],[337,338,339,340,341,342,343,344,345],[167,269],[319,343,350],[269,347,350],[144,320],[269,270,320,323,333,334,335,346],[144,167,303,319],[347,350],[268,270],[270],[350],[320],[167,323],[247,248,271,272,273,274,275,276,321,322,324,325,326,327,328,329,330,331,332],[167,325],[247,248,271,272,273,274,275,276,321,322,324,325,326,327,328,329,330,331,350],[167,268,269],[234,333],[167,270],[317],[144,304],[305,306,307,308,309,310,311,312,313,314,315,316],[304,317,318],[303],[353],[441],[440],[144,167,447],[268],[167,241,353],[144,353,454,455],[438,439,441,442,443,444,445,448,449,450,451,452,453,454,456,457,458,476,477,479,480,481,482,483,486,487,488,489,490,491],[144,167,475],[144,167,353,441,479],[158],[478],[144,167,268,353,477],[144,353,477],[144,353,475,478,480,485,486],[144,167,441,444,456,479,480],[353,455],[486],[536],[536,537,538],[147],[144,147],[145,146,147,148,149,150,151,152,153,154,155,156,159,160,161,162,163,164,165,166],[138,144,145],[135,147,153,155],[147,148],[144,162],[108,362],[360,361,364],[360,363],[108,360],[412,413],[666,667,668,669,670],[666,668],[157],[672,673,674],[73,108],[677],[678],[689],[683,688],[579,581,582,583,584,585,586,587,588,589,590,591],[579,580,582,583,584,585,586,587,588,589,590,591],[580,581,582,583,584,585,586,587,588,589,590,591],[579,580,581,583,584,585,586,587,588,589,590,591],[579,580,581,582,584,585,586,587,588,589,590,591],[579,580,581,582,583,585,586,587,588,589,590,591],[579,580,581,582,583,584,586,587,588,589,590,591],[579,580,581,582,583,584,585,587,588,589,590,591],[579,580,581,582,583,584,585,586,588,589,590,591],[579,580,581,582,583,584,585,586,587,589,590,591],[579,580,581,582,583,584,585,586,587,588,590,591],[579,580,581,582,583,584,585,586,587,588,589,591],[579,580,581,582,583,584,585,586,587,588,589,590],[56],[59],[60,65,92],[61,72,73,80,89,100],[61,62,72,80],[63,101],[64,65,73,81],[65,89,97],[66,68,72,80],[67],[68,69],[72],[71,72],[59,72],[72,73,74,89,100],[72,73,74,89],[72,75,80,89,100],[72,73,75,76,80,89,97,100],[75,77,89,97,100],[56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107],[72,78],[79,100,105],[68,72,80,89],[81],[82],[59,83],[84,99,105],[85],[86],[72,87],[87,88,101,103],[60,72,89,90,91],[60,89,91],[89,90],[92],[93],[72,95,96],[95,96],[65,80,89,97],[98],[80,99],[60,75,86,100],[65,101],[89,102],[103],[104],[60,65,72,74,83,89,100,103,105],[89,106],[108,227],[697,736],[697,721,736],[736],[697],[697,722,736],[697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735],[722,736],[737],[740],[510],[570],[572],[570,571,572,573,574,575,576],[570,572],[446],[593,594,595],[593],[594],[179],[179,180,181,182,183],[168,169,170,171,172,173,174,175,176,177,178],[681,684],[681,684,685,686],[683],[680,687],[682],[137,139,140,141,142,143],[137,138],[139],[138,139],[137,139],[167,188,355,423,531],[532,534],[423,533],[167,188,241],[460,461],[167,184,185,186],[185],[186],[136,185,186,187],[407],[407,408,411,415],[414],[167,409,410],[541,542,543],[223,541],[167,223,541],[167,216,223],[167,188,553,557],[558],[167,216],[167,217],[217,218,219,220,221,222],[135,167,184,188,355,404,405,421],[422],[72,108,167,188],[406],[406,416],[406,417,418,419,420],[167,188,409,416,539,540,549,550],[549],[540,549,551,552],[167,416,544,548],[167,467,468,469],[167,188,416,459,465,467,470],[167,184,188,241,416,459,462,463,464,465,466,468,469,470],[167,188,467],[241,467,468,470],[465,466,467,468,469,470,474],[167,223,467,469,475],[167,223,466,467,468],[471,472,473],[167,223,416,466,468,469],[167,223,466,468,469],[167,223,468,470],[188,416,512,514,515],[513,514],[516],[515,516],[167,188,553,554],[108,167,188,553,554],[554,555,556],[167,553],[72,125,128,135,167,188,241,409,416,462,533,535,553,559,569,577,578,591,592,597,598,600,601,602,603,604,640,641,642,644,645,646,647,648,649,650,651,652,653,661,662,663],[167,597],[167,559,592,597,602],[167,409,410,416,592,597,603],[167,597,599,639],[128,135,167,591,592,597,621,638],[167,416,597],[167,410,416,533,577,592,597,599,643],[72,167,409,553,559,592,597,598,645],[72,167,535,553,577,592,597],[167,409,553,569,577,592,644,647,648],[72,409,416,553,591,592,597],[597,598,600,643,662,664],[135,167,409,553,559,596],[167,416,592,599],[241,597],[167,409,416,559,592,597,598,601],[416,559,597],[167,409,416,592,597,599],[591,596,597],[167,553,592,597],[416,569,592,597],[167,416,592,659],[52,167,416,592,597,599,614,659,660],[409,416,591,592,597,599,600,664],[52,409,416,597,614],[167,416,597,664],[52,241,416,597,600,614],[128,135,167,188,462,535,553,559,569,597,647],[597],[597,639],[72,167,553,559,597],[72,167,535,553,597],[167,409,553,569,644,647,648],[72,409,553,597],[158,167],[167,409,559,597],[559,597],[158,167,409,597],[167,553,597],[569,597],[167,597,614,660],[409,597,664],[409,597],[597,664]],"referencedMap":[[668,1],[126,2],[128,3],[110,4],[132,5],[133,6],[129,6],[135,7],[130,6],[134,8],[131,9],[117,10],[114,11],[121,12],[115,10],[112,13],[125,14],[119,11],[116,15],[118,16],[611,17],[610,18],[609,19],[614,20],[613,21],[619,22],[620,23],[606,24],[607,25],[608,26],[621,27],[616,28],[627,29],[628,30],[623,31],[629,32],[630,33],[631,33],[622,34],[638,35],[633,29],[632,36],[634,37],[624,38],[635,32],[636,30],[626,39],[637,36],[625,40],[617,18],[394,41],[393,42],[395,43],[390,44],[388,44],[389,44],[392,45],[374,46],[379,47],[368,46],[373,48],[372,49],[370,50],[377,51],[378,46],[380,52],[375,53],[367,54],[381,55],[383,56],[384,57],[385,58],[387,59],[358,60],[359,61],[402,62],[403,63],[404,64],[545,65],[546,66],[547,66],[548,67],[260,68],[262,69],[261,70],[257,71],[253,72],[254,72],[258,73],[256,74],[263,75],[264,76],[265,77],[267,78],[266,75],[268,79],[259,80],[252,81],[255,72],[214,82],[215,83],[235,84],[189,85],[190,86],[191,86],[192,85],[197,87],[196,88],[194,82],[195,85],[199,89],[198,85],[202,90],[201,91],[205,92],[203,85],[204,93],[355,94],[207,82],[208,95],[209,96],[210,82],[213,97],[212,98],[236,83],[354,99],[193,100],[658,101],[568,102],[569,103],[561,104],[563,105],[567,106],[565,107],[564,107],[425,108],[424,109],[426,110],[398,111],[399,111],[396,65],[397,112],[401,113],[400,114],[428,115],[431,116],[430,117],[437,118],[433,117],[432,119],[435,117],[434,120],[436,116],[429,116],[225,121],[226,122],[231,123],[229,124],[230,125],[234,126],[232,127],[233,128],[224,129],[238,130],[239,131],[241,132],[237,133],[216,12],[529,134],[530,135],[531,136],[518,137],[519,138],[495,139],[494,140],[496,141],[497,142],[498,143],[504,144],[500,145],[501,146],[499,147],[502,148],[503,149],[525,150],[527,151],[507,152],[509,153],[508,154],[506,155],[505,156],[524,157],[523,158],[522,159],[526,152],[520,133],[521,160],[528,161],[485,162],[484,85],[351,163],[242,164],[352,165],[353,166],[243,167],[244,133],[245,133],[350,168],[348,169],[246,170],[277,133],[278,171],[279,171],[280,171],[281,171],[292,171],[293,171],[294,172],[297,173],[298,171],[295,174],[296,171],[282,171],[284,175],[286,176],[287,177],[285,171],[283,171],[288,178],[289,171],[290,171],[291,179],[299,180],[303,181],[301,171],[300,171],[302,182],[335,183],[337,133],[338,184],[346,185],[339,133],[341,186],[342,133],[344,187],[343,188],[345,189],[347,190],[320,191],[247,184],[248,192],[271,193],[272,194],[273,193],[275,133],[276,195],[321,196],[324,197],[333,198],[326,199],[325,133],[327,133],[328,164],[332,200],[329,195],[330,197],[331,184],[270,201],[334,202],[323,203],[318,204],[305,205],[314,205],[306,205],[307,205],[316,205],[308,205],[309,205],[317,206],[315,205],[310,205],[313,205],[311,205],[312,205],[319,207],[304,86],[455,208],[439,209],[442,210],[443,211],[445,210],[448,212],[451,213],[453,214],[456,215],[492,216],[476,217],[458,133],[480,218],[481,219],[479,220],[478,221],[482,222],[487,223],[477,100],[486,224],[489,225],[490,226],[491,133],[441,211],[537,227],[538,227],[539,228],[145,86],[146,86],[148,229],[149,86],[150,86],[151,230],[147,86],[167,231],[155,232],[156,233],[159,219],[165,234],[166,235],[363,236],[362,11],[365,237],[360,11],[364,238],[361,239],[414,240],[671,241],[667,1],[669,242],[670,1],[410,11],[158,243],[675,244],[676,245],[678,246],[679,247],[690,248],[689,249],[580,250],[581,251],[579,252],[582,253],[583,254],[584,255],[585,256],[586,257],[587,258],[588,259],[589,260],[590,261],[591,262],[56,263],[57,263],[59,264],[60,265],[61,266],[62,267],[63,268],[64,269],[65,270],[66,271],[67,272],[68,273],[69,273],[70,274],[71,275],[72,276],[73,277],[74,278],[75,279],[76,280],[77,281],[108,282],[78,283],[79,284],[80,285],[81,286],[82,287],[83,288],[84,289],[85,290],[86,291],[87,292],[88,293],[89,294],[91,295],[90,296],[92,297],[93,298],[95,299],[96,300],[97,301],[98,302],[99,303],[100,304],[101,305],[102,306],[103,307],[104,308],[105,309],[106,310],[694,11],[228,311],[696,11],[721,312],[722,313],[697,314],[700,314],[719,312],[720,312],[710,312],[709,315],[707,312],[702,312],[715,312],[713,312],[717,312],[701,312],[714,312],[718,312],[703,312],[704,312],[716,312],[698,312],[705,312],[706,312],[708,312],[712,312],[723,316],[711,312],[699,312],[736,317],[730,316],[732,318],[731,316],[724,316],[725,316],[727,316],[729,316],[733,318],[734,318],[726,318],[728,318],[738,319],[741,320],[511,321],[571,322],[573,323],[577,324],[575,325],[574,325],[447,326],[596,327],[594,328],[595,329],[175,330],[177,330],[176,330],[174,330],[184,331],[179,332],[170,330],[171,330],[172,330],[173,330],[685,333],[687,334],[686,333],[684,335],[688,336],[683,337],[144,338],[139,339],[140,340],[141,340],[142,341],[143,341],[138,342],[532,343],[535,344],[534,345],[460,346],[462,347],[187,348],[186,349],[185,350],[188,351],[408,352],[416,353],[415,354],[411,355],[544,356],[542,357],[543,358],[541,359],[558,360],[559,361],[217,362],[218,363],[219,363],[221,363],[223,364],[222,363],[422,365],[423,366],[406,367],[420,368],[419,368],[417,369],[418,368],[421,370],[551,371],[550,372],[552,372],[553,373],[549,374],[470,375],[468,376],[467,377],[465,378],[469,379],[475,380],[464,381],[471,382],[474,383],[472,384],[473,385],[466,386],[516,387],[515,388],[517,389],[514,390],[555,391],[556,392],[557,393],[554,394],[664,395],[659,396],[603,397],[604,398],[640,399],[639,400],[641,399],[642,401],[644,402],[646,403],[647,404],[649,405],[648,406],[665,407],[592,133],[597,408],[643,409],[650,410],[602,411],[598,412],[651,413],[652,414],[645,415],[653,416],[660,417],[661,418],[601,419],[662,420],[600,421],[663,422]],"exportedModulesMap":[[668,1],[126,2],[128,3],[110,4],[132,5],[133,6],[129,6],[135,7],[130,6],[134,8],[131,9],[117,10],[114,11],[121,12],[115,10],[112,13],[125,14],[119,11],[116,15],[118,16],[611,17],[610,18],[609,19],[614,20],[613,21],[619,22],[620,23],[606,24],[607,25],[608,26],[621,27],[616,28],[627,29],[628,30],[623,31],[629,32],[630,33],[631,33],[622,34],[638,35],[633,29],[632,36],[634,37],[624,38],[635,32],[636,30],[626,39],[637,36],[625,40],[617,18],[394,41],[393,42],[395,43],[390,44],[388,44],[389,44],[392,45],[374,46],[379,47],[368,46],[373,48],[372,49],[370,50],[377,51],[378,46],[380,52],[375,53],[367,54],[381,55],[383,56],[384,57],[385,58],[387,59],[358,60],[359,61],[402,62],[403,63],[404,64],[545,65],[546,66],[547,66],[548,67],[260,68],[262,69],[261,70],[257,71],[253,72],[254,72],[258,73],[256,74],[263,75],[264,76],[265,77],[267,78],[266,75],[268,79],[259,80],[252,81],[255,72],[214,82],[215,83],[235,84],[189,85],[190,86],[191,86],[192,85],[197,87],[196,88],[194,82],[195,85],[199,89],[198,85],[202,90],[201,91],[205,92],[203,85],[204,93],[355,94],[207,82],[208,95],[209,96],[210,82],[213,97],[212,98],[236,83],[354,99],[193,100],[658,101],[568,102],[569,103],[561,104],[563,105],[567,106],[565,107],[564,107],[425,108],[424,109],[426,110],[398,111],[399,111],[396,65],[397,112],[401,113],[400,114],[428,115],[431,116],[430,117],[437,118],[433,117],[432,119],[435,117],[434,120],[436,116],[429,116],[225,121],[226,122],[231,123],[229,124],[230,125],[234,126],[232,127],[233,128],[224,129],[238,130],[239,131],[241,132],[237,133],[216,12],[529,134],[530,135],[531,136],[518,137],[519,138],[495,139],[494,140],[496,141],[497,142],[498,143],[504,144],[500,145],[501,146],[499,147],[502,148],[503,149],[525,150],[527,151],[507,152],[509,153],[508,154],[506,155],[505,156],[524,157],[523,158],[522,159],[526,152],[520,133],[521,160],[528,161],[485,162],[484,85],[351,163],[242,164],[352,165],[353,166],[243,167],[244,133],[245,133],[350,168],[348,169],[246,170],[277,133],[278,171],[279,171],[280,171],[281,171],[292,171],[293,171],[294,172],[297,173],[298,171],[295,174],[296,171],[282,171],[284,175],[286,176],[287,177],[285,171],[283,171],[288,178],[289,171],[290,171],[291,179],[299,180],[303,181],[301,171],[300,171],[302,182],[335,183],[337,133],[338,184],[346,185],[339,133],[341,186],[342,133],[344,187],[343,188],[345,189],[347,190],[320,191],[247,184],[248,192],[271,193],[272,194],[273,193],[275,133],[276,195],[321,196],[324,197],[333,198],[326,199],[325,133],[327,133],[328,164],[332,200],[329,195],[330,197],[331,184],[270,201],[334,202],[323,203],[318,204],[305,205],[314,205],[306,205],[307,205],[316,205],[308,205],[309,205],[317,206],[315,205],[310,205],[313,205],[311,205],[312,205],[319,207],[304,86],[455,208],[439,209],[442,210],[443,211],[445,210],[448,212],[451,213],[453,214],[456,215],[492,216],[476,217],[458,133],[480,218],[481,219],[479,220],[478,221],[482,222],[487,223],[477,100],[486,224],[489,225],[490,226],[491,133],[441,211],[537,227],[538,227],[539,228],[145,86],[146,86],[148,229],[149,86],[150,86],[151,230],[147,86],[167,231],[155,232],[156,233],[159,219],[165,234],[166,235],[363,236],[362,11],[365,237],[360,11],[364,238],[361,239],[414,240],[671,241],[667,1],[669,242],[670,1],[410,11],[158,243],[675,244],[676,245],[678,246],[679,247],[690,248],[689,249],[580,250],[581,251],[579,252],[582,253],[583,254],[584,255],[585,256],[586,257],[587,258],[588,259],[589,260],[590,261],[591,262],[56,263],[57,263],[59,264],[60,265],[61,266],[62,267],[63,268],[64,269],[65,270],[66,271],[67,272],[68,273],[69,273],[70,274],[71,275],[72,276],[73,277],[74,278],[75,279],[76,280],[77,281],[108,282],[78,283],[79,284],[80,285],[81,286],[82,287],[83,288],[84,289],[85,290],[86,291],[87,292],[88,293],[89,294],[91,295],[90,296],[92,297],[93,298],[95,299],[96,300],[97,301],[98,302],[99,303],[100,304],[101,305],[102,306],[103,307],[104,308],[105,309],[106,310],[694,11],[228,311],[696,11],[721,312],[722,313],[697,314],[700,314],[719,312],[720,312],[710,312],[709,315],[707,312],[702,312],[715,312],[713,312],[717,312],[701,312],[714,312],[718,312],[703,312],[704,312],[716,312],[698,312],[705,312],[706,312],[708,312],[712,312],[723,316],[711,312],[699,312],[736,317],[730,316],[732,318],[731,316],[724,316],[725,316],[727,316],[729,316],[733,318],[734,318],[726,318],[728,318],[738,319],[741,320],[511,321],[571,322],[573,323],[577,324],[575,325],[574,325],[447,326],[596,327],[594,328],[595,329],[175,330],[177,330],[176,330],[174,330],[184,331],[179,332],[170,330],[171,330],[172,330],[173,330],[685,333],[687,334],[686,333],[684,335],[688,336],[683,337],[144,338],[139,339],[140,340],[141,340],[142,341],[143,341],[138,342],[532,343],[535,344],[534,345],[460,346],[462,347],[187,348],[186,349],[185,350],[188,351],[408,352],[416,353],[415,354],[411,355],[544,356],[542,357],[543,358],[541,359],[558,360],[559,361],[217,362],[218,363],[219,363],[221,363],[223,364],[222,363],[422,365],[423,366],[406,367],[420,368],[419,368],[417,369],[418,368],[421,370],[551,371],[550,372],[552,372],[553,373],[549,374],[470,375],[468,376],[467,377],[465,378],[469,379],[475,380],[464,381],[471,382],[474,383],[472,384],[473,385],[466,386],[516,387],[515,388],[517,389],[514,390],[555,391],[556,392],[557,393],[554,394],[664,423],[659,133],[603,424],[604,424],[640,425],[639,396],[641,425],[642,424],[644,396],[646,426],[647,427],[649,428],[648,429],[665,407],[592,430],[597,408],[643,133],[650,424],[602,431],[598,432],[651,433],[652,424],[645,434],[653,435],[660,133],[661,436],[601,437],[662,438],[600,439],[663,424]],"semanticDiagnosticsPerFile":[668,666,126,109,128,110,127,132,133,129,135,130,134,131,117,114,121,115,112,120,125,122,123,124,119,116,113,118,611,610,609,614,613,619,620,606,607,608,605,621,616,615,612,627,628,623,629,630,631,622,638,633,632,634,624,635,636,626,637,625,617,618,394,393,395,390,388,389,392,391,374,379,368,373,372,370,377,378,380,375,369,367,366,376,382,381,383,384,385,387,357,358,359,356,371,386,402,403,404,405,545,546,547,548,409,260,262,261,249,257,253,254,258,256,263,264,265,267,266,268,259,252,250,251,255,214,215,235,189,190,191,192,197,196,194,195,199,198,200,202,201,205,203,204,206,355,207,208,209,210,213,211,212,236,354,193,656,654,655,657,658,568,569,561,560,563,562,566,567,565,564,425,424,426,398,399,396,397,401,400,428,431,430,437,433,432,435,434,436,427,429,225,226,231,229,230,234,232,233,224,238,240,239,241,237,216,529,530,531,518,519,495,494,496,497,498,504,500,501,499,502,503,525,493,527,507,509,508,506,505,524,523,522,526,520,521,528,485,484,351,242,352,353,243,244,245,350,348,246,349,277,278,279,280,281,292,293,294,297,298,295,296,282,284,286,287,285,283,288,289,290,291,299,303,301,300,302,269,335,337,338,346,339,340,341,342,344,343,345,336,347,320,247,248,271,272,273,274,275,276,321,322,324,333,326,325,327,328,332,329,330,331,270,334,323,318,305,314,306,307,316,308,309,317,315,310,313,311,312,319,304,455,438,439,442,443,444,445,448,449,450,451,452,453,454,456,457,492,476,458,480,481,479,478,482,483,487,488,477,486,489,490,491,440,441,537,538,539,536,145,146,148,149,150,151,152,153,154,147,167,155,156,159,160,161,162,163,164,165,166,363,362,365,360,364,361,412,414,413,671,667,669,670,410,158,463,672,675,673,676,677,678,679,690,689,674,691,580,581,579,582,583,584,585,586,587,588,589,590,591,692,157,56,57,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,58,107,75,76,77,108,78,79,80,81,82,83,84,85,86,87,88,89,91,90,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,693,694,695,512,228,227,696,721,722,697,700,719,720,710,709,707,702,715,713,717,701,714,718,703,704,716,698,705,706,708,712,723,711,699,736,735,730,732,731,724,725,727,729,733,734,726,728,738,737,739,533,740,741,511,510,571,570,573,572,576,577,575,574,111,680,446,447,578,596,594,595,593,513,178,175,177,176,174,184,179,183,180,182,181,170,171,172,168,169,173,681,685,687,686,684,688,459,683,682,137,144,139,140,141,142,143,138,8,10,9,2,11,12,13,14,15,16,17,18,3,4,22,19,20,21,23,24,25,5,26,27,28,29,6,33,30,31,32,34,7,35,40,41,36,37,38,39,1,42,532,535,534,460,461,462,136,187,186,185,188,408,416,415,407,411,544,542,543,541,558,559,217,218,219,220,221,223,222,422,423,406,420,419,417,418,421,551,540,550,552,553,549,470,468,467,465,469,475,464,471,474,472,473,466,516,515,517,514,555,556,557,554,664,599,659,603,604,640,639,641,642,644,646,647,649,648,665,592,597,643,650,602,598,651,652,645,653,660,661,601,662,600,663,47,48,49,50,51,52,43,53,54,55,44,45,46],"latestChangedDtsFile":"./types/index.d.ts"},"version":"4.9.5"}
+\ No newline at end of file
++{"program":{"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.esnext.intl.d.ts","../../../types/eth-ens-namehash.d.ts","../../../types/ethereum-ens-network-map.d.ts","../../../types/global.d.ts","../../../types/single-call-balance-checker-abi.d.ts","../../../types/@metamask/contract-metadata.d.ts","../../../types/@metamask/eth-hd-keyring.d.ts","../../../types/@metamask/eth-simple-keyring.d.ts","../../../types/@metamask/ethjs-provider-http.d.ts","../../../types/@metamask/ethjs-unit.d.ts","../../../types/@metamask/metamask-eth-abis.d.ts","../../../types/eth-json-rpc-infura/src/createprovider.d.ts","../../../types/eth-phishing-detect/src/config.json.d.ts","../../../types/eth-phishing-detect/src/detector.d.ts","../../../node_modules/@types/node/assert.d.ts","../../../node_modules/@types/node/assert/strict.d.ts","../../../node_modules/@types/node/globals.d.ts","../../../node_modules/@types/node/async_hooks.d.ts","../../../node_modules/@types/node/buffer.d.ts","../../../node_modules/@types/node/child_process.d.ts","../../../node_modules/@types/node/cluster.d.ts","../../../node_modules/@types/node/console.d.ts","../../../node_modules/@types/node/constants.d.ts","../../../node_modules/@types/node/crypto.d.ts","../../../node_modules/@types/node/dgram.d.ts","../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../node_modules/@types/node/dns.d.ts","../../../node_modules/@types/node/dns/promises.d.ts","../../../node_modules/@types/node/dom-events.d.ts","../../../node_modules/@types/node/domain.d.ts","../../../node_modules/@types/node/events.d.ts","../../../node_modules/@types/node/fs.d.ts","../../../node_modules/@types/node/fs/promises.d.ts","../../../node_modules/@types/node/http.d.ts","../../../node_modules/@types/node/http2.d.ts","../../../node_modules/@types/node/https.d.ts","../../../node_modules/@types/node/inspector.d.ts","../../../node_modules/@types/node/module.d.ts","../../../node_modules/@types/node/net.d.ts","../../../node_modules/@types/node/os.d.ts","../../../node_modules/@types/node/path.d.ts","../../../node_modules/@types/node/perf_hooks.d.ts","../../../node_modules/@types/node/process.d.ts","../../../node_modules/@types/node/punycode.d.ts","../../../node_modules/@types/node/querystring.d.ts","../../../node_modules/@types/node/readline.d.ts","../../../node_modules/@types/node/repl.d.ts","../../../node_modules/@types/node/stream.d.ts","../../../node_modules/@types/node/stream/promises.d.ts","../../../node_modules/@types/node/stream/consumers.d.ts","../../../node_modules/@types/node/stream/web.d.ts","../../../node_modules/@types/node/string_decoder.d.ts","../../../node_modules/@types/node/test.d.ts","../../../node_modules/@types/node/timers.d.ts","../../../node_modules/@types/node/timers/promises.d.ts","../../../node_modules/@types/node/tls.d.ts","../../../node_modules/@types/node/trace_events.d.ts","../../../node_modules/@types/node/tty.d.ts","../../../node_modules/@types/node/url.d.ts","../../../node_modules/@types/node/util.d.ts","../../../node_modules/@types/node/v8.d.ts","../../../node_modules/@types/node/vm.d.ts","../../../node_modules/@types/node/wasi.d.ts","../../../node_modules/@types/node/worker_threads.d.ts","../../../node_modules/@types/node/zlib.d.ts","../../../node_modules/@types/node/globals.global.d.ts","../../../node_modules/@types/node/index.d.ts","../../../node_modules/@ethereumjs/common/dist/enums.d.ts","../../../node_modules/@ethereumjs/common/dist/types.d.ts","../../../node_modules/buffer/index.d.ts","../../../node_modules/@ethereumjs/util/dist/constants.d.ts","../../../node_modules/@ethereumjs/util/dist/units.d.ts","../../../node_modules/@ethereumjs/util/dist/address.d.ts","../../../node_modules/@ethereumjs/util/dist/bytes.d.ts","../../../node_modules/@ethereumjs/util/dist/types.d.ts","../../../node_modules/@ethereumjs/util/dist/account.d.ts","../../../node_modules/@ethereumjs/util/dist/withdrawal.d.ts","../../../node_modules/@ethereumjs/util/dist/signature.d.ts","../../../node_modules/@ethereumjs/util/dist/encoding.d.ts","../../../node_modules/@ethereumjs/util/dist/asynceventemitter.d.ts","../../../node_modules/@ethereumjs/util/dist/internal.d.ts","../../../node_modules/@ethereumjs/util/dist/lock.d.ts","../../../node_modules/@ethereumjs/util/dist/provider.d.ts","../../../node_modules/@ethereumjs/util/dist/index.d.ts","../../../node_modules/@ethereumjs/common/dist/common.d.ts","../../../node_modules/@ethereumjs/common/dist/utils.d.ts","../../../node_modules/@ethereumjs/common/dist/index.d.ts","../../../node_modules/@ethereumjs/tx/dist/eip2930transaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/legacytransaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/types.d.ts","../../../node_modules/@ethereumjs/tx/dist/basetransaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/eip1559transaction.d.ts","../../../node_modules/@ethereumjs/tx/dist/transactionfactory.d.ts","../../../node_modules/@ethereumjs/tx/dist/index.d.ts","../../base-controller/dist/types/basecontrollerv1.d.ts","../../../node_modules/superstruct/dist/error.d.ts","../../../node_modules/superstruct/dist/utils.d.ts","../../../node_modules/superstruct/dist/struct.d.ts","../../../node_modules/superstruct/dist/structs/coercions.d.ts","../../../node_modules/superstruct/dist/structs/refinements.d.ts","../../../node_modules/superstruct/dist/structs/types.d.ts","../../../node_modules/superstruct/dist/structs/utilities.d.ts","../../../node_modules/superstruct/dist/index.d.ts","../../../node_modules/@metamask/utils/dist/types/assert.d.ts","../../../node_modules/@metamask/utils/dist/types/base64.d.ts","../../../node_modules/@metamask/utils/dist/types/hex.d.ts","../../../node_modules/@metamask/utils/dist/types/bytes.d.ts","../../../node_modules/@metamask/utils/dist/types/caip-types.d.ts","../../../node_modules/@metamask/utils/dist/types/checksum.d.ts","../../../node_modules/@metamask/utils/dist/types/coercers.d.ts","../../../node_modules/@metamask/utils/dist/types/collections.d.ts","../../../node_modules/@metamask/utils/dist/types/encryption-types.d.ts","../../../node_modules/@metamask/utils/dist/types/errors.d.ts","../../../node_modules/@metamask/utils/dist/types/json.d.ts","../../../node_modules/@metamask/utils/dist/types/keyring.d.ts","../../../node_modules/@types/ms/index.d.ts","../../../node_modules/@types/debug/index.d.ts","../../../node_modules/@metamask/utils/dist/types/logging.d.ts","../../../node_modules/@metamask/utils/dist/types/misc.d.ts","../../../node_modules/@metamask/utils/dist/types/number.d.ts","../../../node_modules/@metamask/utils/dist/types/opaque.d.ts","../../../node_modules/@metamask/utils/dist/types/promise.d.ts","../../../node_modules/@metamask/utils/dist/types/time.d.ts","../../../node_modules/@metamask/utils/dist/types/transaction-types.d.ts","../../../node_modules/@metamask/utils/dist/types/versions.d.ts","../../../node_modules/@metamask/utils/dist/types/index.d.ts","../../../node_modules/immer/dist/utils/env.d.ts","../../../node_modules/immer/dist/utils/errors.d.ts","../../../node_modules/immer/dist/types/types-external.d.ts","../../../node_modules/immer/dist/types/types-internal.d.ts","../../../node_modules/immer/dist/utils/common.d.ts","../../../node_modules/immer/dist/utils/plugins.d.ts","../../../node_modules/immer/dist/core/scope.d.ts","../../../node_modules/immer/dist/core/finalize.d.ts","../../../node_modules/immer/dist/core/proxy.d.ts","../../../node_modules/immer/dist/core/immerclass.d.ts","../../../node_modules/immer/dist/core/current.d.ts","../../../node_modules/immer/dist/internal.d.ts","../../../node_modules/immer/dist/plugins/es5.d.ts","../../../node_modules/immer/dist/plugins/patches.d.ts","../../../node_modules/immer/dist/plugins/mapset.d.ts","../../../node_modules/immer/dist/plugins/all.d.ts","../../../node_modules/immer/dist/immer.d.ts","../../base-controller/dist/types/restrictedcontrollermessenger.d.ts","../../base-controller/dist/types/controllermessenger.d.ts","../../base-controller/dist/types/basecontrollerv2.d.ts","../../base-controller/dist/types/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/account.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/balance.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/caip.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/export.d.ts","../../../node_modules/@metamask/keyring-api/dist/superstruct.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/request.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/response.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/keyring.d.ts","../../../node_modules/@metamask/keyring-api/dist/api/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/btc/types.d.ts","../../../node_modules/@metamask/keyring-api/dist/btc/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/contexts.d.ts","../../../node_modules/@metamask/keyring-api/dist/eth/erc4337/types.d.ts","../../../node_modules/@metamask/keyring-api/dist/eth/erc4337/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/eth/types.d.ts","../../../node_modules/@metamask/keyring-api/dist/eth/utils.d.ts","../../../node_modules/@metamask/keyring-api/dist/eth/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/events.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/api.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/eth/ethkeyring.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/eth/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/events.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/rpc.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/types.d.ts","../../../node_modules/@metamask/keyring-api/dist/internal/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/jsonrpcrequest.d.ts","../../../node_modules/@metamask/keyring-api/dist/keyringclient.d.ts","../../../node_modules/@metamask/safe-event-emitter/dist/cjs/index.d.ts","../../json-rpc-engine/dist/types/jsonrpcengine.d.ts","../../json-rpc-engine/dist/types/createasyncmiddleware.d.ts","../../json-rpc-engine/dist/types/createscaffoldmiddleware.d.ts","../../json-rpc-engine/dist/types/getuniqueid.d.ts","../../json-rpc-engine/dist/types/idremapmiddleware.d.ts","../../json-rpc-engine/dist/types/mergemiddleware.d.ts","../../json-rpc-engine/dist/types/index.d.ts","../../../node_modules/@metamask/providers/dist/types/utils.d.ts","../../../node_modules/@metamask/providers/dist/types/baseprovider.d.ts","../../../node_modules/@metamask/providers/dist/types/eip6963.d.ts","../../../node_modules/@types/readable-stream/node_modules/safe-buffer/index.d.ts","../../../node_modules/@types/readable-stream/index.d.ts","../../../node_modules/@metamask/providers/dist/types/streamprovider.d.ts","../../../node_modules/@metamask/providers/dist/types/extension-provider/createexternalextensionprovider.d.ts","../../../node_modules/@metamask/providers/dist/types/metamaskinpageprovider.d.ts","../../../node_modules/@metamask/providers/dist/types/initializeinpageprovider.d.ts","../../../node_modules/@metamask/providers/dist/types/shimweb3.d.ts","../../../node_modules/@metamask/providers/dist/types/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/keyringsnaprpcclient.d.ts","../../../node_modules/@metamask/keyring-api/dist/rpc-handler.d.ts","../../../node_modules/@metamask/rpc-errors/dist/types/utils.d.ts","../../../node_modules/@metamask/rpc-errors/dist/types/classes.d.ts","../../../node_modules/@metamask/rpc-errors/dist/types/errors.d.ts","../../../node_modules/@metamask/rpc-errors/dist/types/error-constants.d.ts","../../../node_modules/@metamask/rpc-errors/dist/types/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/errors.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/error-wrappers.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/errors.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/helpers.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/structs.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/create-interface.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/dialog.d.ts","../../../node_modules/@metamask/key-tree/dist/constants.d.cts","../../../node_modules/@metamask/key-tree/node_modules/@noble/curves/abstract/modular.d.ts","../../../node_modules/@metamask/key-tree/node_modules/@noble/curves/abstract/utils.d.ts","../../../node_modules/@metamask/key-tree/node_modules/@noble/curves/abstract/curve.d.ts","../../../node_modules/@metamask/key-tree/dist/curves/ed25519.d.cts","../../../node_modules/@metamask/key-tree/dist/curves/ed25519bip32.d.cts","../../../node_modules/@metamask/key-tree/node_modules/@noble/curves/abstract/weierstrass.d.ts","../../../node_modules/@metamask/key-tree/dist/curves/secp256k1.d.cts","../../../node_modules/@metamask/key-tree/dist/curves/curve.d.cts","../../../node_modules/@metamask/key-tree/dist/curves/index.d.cts","../../../node_modules/@metamask/key-tree/dist/utils.d.cts","../../../node_modules/@metamask/key-tree/dist/bip44cointypenode.d.cts","../../../node_modules/@metamask/key-tree/dist/slip10node.d.cts","../../../node_modules/@metamask/key-tree/dist/bip44node.d.cts","../../../node_modules/@metamask/key-tree/dist/derivers/bip32.d.cts","../../../node_modules/@metamask/key-tree/dist/derivers/bip39.d.cts","../../../node_modules/@metamask/key-tree/dist/derivers/cip3.d.cts","../../../node_modules/@metamask/key-tree/dist/derivers/slip10.d.cts","../../../node_modules/@metamask/key-tree/dist/derivers/index.d.cts","../../../node_modules/@metamask/key-tree/dist/index.d.cts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/caip.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/permissions.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-bip32-entropy.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-bip32-public-key.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-bip44-entropy.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-client-status.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-entropy.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-file.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/component.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/address.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/box.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/copyable.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/divider.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/button.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/option.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/dropdown.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/input.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/field.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/form.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/form/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/formatting/bold.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/formatting/italic.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/formatting/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/heading.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/image.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/link.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/text.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/value.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/row.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/spinner.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/components/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/jsx-runtime.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/jsx-dev-runtime.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/validation.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/jsx/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/nodes.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/address.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/copyable.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/divider.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/heading.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/image.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/panel.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/spinner.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/text.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/row.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/button.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/input.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/form.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/components/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/component.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/ui/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/interface.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-interface-state.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-locale.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/snap.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/get-snaps.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/invoke-snap.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/invoke-keyring.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/manage-accounts.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/manage-state.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/notify.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/request-snaps.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/update-interface.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/methods.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/methods/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/provider.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/global.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/images.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/cronjob.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/home-page.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/keyring.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/lifecycle.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/name-lookup.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/rpc-request.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/transaction.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/signature.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/user-input.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/handlers/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/types/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/jsx.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/svg.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/internals/index.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/error-wrappers.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/images.d.ts","../../../node_modules/@metamask/snaps-sdk/dist/types/index.d.ts","../../../node_modules/@metamask/keyring-api/dist/snap-utils.d.ts","../../../node_modules/@metamask/keyring-api/dist/index.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/patchcbor.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/lib/dataitem.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/lib/cbor-sync.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/lib/index.d.ts","../../../node_modules/@ngraveio/bc-ur/dist/ur.d.ts","../../../node_modules/@ngraveio/bc-ur/dist/urencoder.d.ts","../../../node_modules/@ngraveio/bc-ur/dist/fountainencoder.d.ts","../../../node_modules/@ngraveio/bc-ur/dist/fountaindecoder.d.ts","../../../node_modules/@ngraveio/bc-ur/dist/urdecoder.d.ts","../../../node_modules/@ngraveio/bc-ur/dist/index.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/registrytype.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/registryitem.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/cryptocoininfo.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/pathcomponent.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/cryptokeypath.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/types.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/cryptohdkey.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/cryptoeckey.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/bytes.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/multikey.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/scriptexpression.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/cryptooutput.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/cryptopsbt.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/cryptoaccount.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/decoder/index.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/extended/cryptomultiaccounts.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/errors/index.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/extended/derivationschema.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/extended/keyderivation.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/extended/qrhardwarecall.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/utils.d.ts","../../../node_modules/@keystonehq/bc-ur-registry/dist/index.d.ts","../../../node_modules/@keystonehq/bc-ur-registry-eth/dist/ethsignrequest.d.ts","../../../node_modules/@keystonehq/bc-ur-registry-eth/dist/ethsignature.d.ts","../../../node_modules/@keystonehq/bc-ur-registry-eth/dist/ethnftitem.d.ts","../../../node_modules/@keystonehq/bc-ur-registry-eth/dist/utlis.d.ts","../../../node_modules/@keystonehq/bc-ur-registry-eth/dist/index.d.ts","../../../node_modules/@keystonehq/base-eth-keyring/dist/interactionprovider.d.ts","../../../node_modules/@keystonehq/base-eth-keyring/dist/basekeyring.d.ts","../../../node_modules/@keystonehq/base-eth-keyring/dist/index.d.ts","../../../node_modules/@metamask/obs-store/dist/observablestore.d.ts","../../../node_modules/@metamask/obs-store/dist/asstream.d.ts","../../../node_modules/@metamask/obs-store/dist/composedstore.d.ts","../../../node_modules/@metamask/obs-store/dist/mergedstore.d.ts","../../../node_modules/@metamask/obs-store/dist/transform.d.ts","../../../node_modules/@metamask/obs-store/dist/index.d.ts","../../../node_modules/@keystonehq/metamask-airgapped-keyring/dist/metamaskinteractionprovider.d.ts","../../../node_modules/@keystonehq/metamask-airgapped-keyring/dist/metamaskkeyring.d.ts","../../../node_modules/@keystonehq/metamask-airgapped-keyring/dist/index.d.ts","../../../node_modules/@metamask/browser-passworder/dist/index.d.ts","../../message-manager/dist/types/abstractmessagemanager.d.ts","../../controller-utils/dist/types/types.d.ts","../../controller-utils/dist/types/constants.d.ts","../../../node_modules/@metamask/eth-query/index.d.ts","../../../node_modules/@types/bn.js/index.d.ts","../../controller-utils/dist/types/util.d.ts","../../../node_modules/@spruceid/siwe-parser/dist/abnf.d.ts","../../../node_modules/@spruceid/siwe-parser/dist/utils.d.ts","../../../node_modules/@spruceid/siwe-parser/dist/parsers.d.ts","../../controller-utils/dist/types/siwe.d.ts","../../controller-utils/dist/types/index.d.ts","../../message-manager/dist/types/personalmessagemanager.d.ts","../../message-manager/dist/types/typedmessagemanager.d.ts","../../message-manager/dist/types/encryptionpublickeymanager.d.ts","../../message-manager/dist/types/decryptmessagemanager.d.ts","../../message-manager/dist/types/index.d.ts","../../keyring-controller/dist/types/keyringcontroller.d.ts","../../keyring-controller/dist/types/index.d.ts","../../../node_modules/@metamask/object-multiplex/dist/substream.d.ts","../../../node_modules/@metamask/object-multiplex/dist/objectmultiplex.d.ts","../../../node_modules/@metamask/object-multiplex/dist/index.d.ts","../../../node_modules/@metamask/post-message-stream/dist/utils.d.ts","../../../node_modules/@metamask/post-message-stream/dist/basepostmessagestream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/window/windowpostmessagestream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/webworker/webworkerpostmessagestream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/webworker/webworkerparentpostmessagestream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/node-process/processparentmessagestream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/node-process/processmessagestream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/node-thread/threadparentmessagestream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/node-thread/threadmessagestream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/runtime/browserruntimepostmessagestream.d.ts","../../../node_modules/@metamask/post-message-stream/dist/index.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/array.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/auxiliary-files.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/virtual-file/virtualfile.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/virtual-file/index.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/base64.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/bytes.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/caveats.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/checksum.d.ts","../../../node_modules/cron-parser/types/common.d.ts","../../../node_modules/cron-parser/types/index.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/cronjob.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/deep-clone.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/default-endowments.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/derivation-paths.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/entropy.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/errors.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/handler-types.d.ts","../../../node_modules/@metamask/snaps-sdk/jsx.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/handlers.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/iframe.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/json.d.ts","../../../node_modules/nanoid/index.d.ts","../../approval-controller/dist/types/approvalcontroller.d.ts","../../approval-controller/dist/types/errors.d.ts","../../approval-controller/dist/types/index.d.ts","../../../node_modules/@types/deep-freeze-strict/index.d.ts","../../permission-controller/src/permission-middleware.ts","../../permission-controller/src/subjectmetadatacontroller.ts","../../permission-controller/src/utils.ts","../../permission-controller/src/permissioncontroller.ts","../../permission-controller/src/permission.ts","../../permission-controller/src/errors.ts","../../permission-controller/src/caveat.ts","../../permission-controller/src/rpc-methods/getpermissions.ts","../../permission-controller/src/rpc-methods/requestpermissions.ts","../../permission-controller/src/rpc-methods/revokepermissions.ts","../../permission-controller/src/rpc-methods/index.ts","../../permission-controller/src/index.ts","../../../node_modules/@metamask/snaps-utils/dist/types/json-rpc.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/structs.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/manifest/validation.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/manifest/index.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/localization.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/logging.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/namespace.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/path.d.ts","../../../node_modules/@metamask/snaps-registry/dist/verify.d.ts","../../../node_modules/@metamask/snaps-registry/dist/index.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/types.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/snaps.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/strings.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/ui.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/validation.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/versions.d.ts","../../../node_modules/@metamask/snaps-utils/dist/types/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/timer.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/executionservice.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/abstractexecutionservice.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/proxypostmessagestream.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/iframe/iframeexecutionservice.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/iframe/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/proxy/proxyexecutionservice.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/offscreen/offscreenexecutionservice.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/offscreen/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/webworker/webworkerexecutionservice.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/webworker/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/services/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/location/npm.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/location/location.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/location/http.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/location/local.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/location/index.d.ts","../../../node_modules/@xstate/fsm/lib/types.d.ts","../../../node_modules/@xstate/fsm/lib/index.d.ts","../../../node_modules/@types/punycode/index.d.ts","../../../node_modules/fastest-levenshtein/mod.d.ts","../../phishing-controller/src/utils.ts","../../phishing-controller/src/phishingdetector.ts","../../phishing-controller/src/phishingcontroller.ts","../../phishing-controller/src/index.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/interface/snapinterfacecontroller.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/interface/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/types/encryptor.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/types/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/registry/registry.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/registry/json.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/registry/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/snapcontroller.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/selectors.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/snaps/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/utils.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/cronjob/cronjobcontroller.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/cronjob/index.d.ts","../../../node_modules/@metamask/snaps-controllers/dist/types/index.d.ts","../../accounts-controller/dist/types/accountscontroller.d.ts","../../../node_modules/@types/uuid/index.d.ts","../../accounts-controller/dist/types/utils.d.ts","../../accounts-controller/dist/types/index.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/types.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/createeventemitterproxy.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/createswappableproxy.d.ts","../../../node_modules/@metamask/swappable-obj-proxy/dist/index.d.ts","../../network-controller/dist/types/constants.d.ts","../../eth-json-rpc-provider/dist/types/safe-event-emitter-provider.d.ts","../../eth-json-rpc-provider/dist/types/provider-from-engine.d.ts","../../eth-json-rpc-provider/dist/types/provider-from-middleware.d.ts","../../eth-json-rpc-provider/dist/types/index.d.ts","../../../node_modules/@metamask/eth-block-tracker/dist/blocktracker.d.ts","../../../node_modules/@metamask/eth-block-tracker/dist/pollingblocktracker.d.ts","../../../node_modules/@metamask/eth-block-tracker/dist/subscribeblocktracker.d.ts","../../../node_modules/@metamask/eth-block-tracker/dist/index.d.ts","../../network-controller/dist/types/types.d.ts","../../network-controller/dist/types/create-auto-managed-network-client.d.ts","../../network-controller/dist/types/networkcontroller.d.ts","../../network-controller/dist/types/create-network-client.d.ts","../../network-controller/dist/types/index.d.ts","../../polling-controller/dist/types/types.d.ts","../../polling-controller/dist/types/blocktrackerpollingcontroller.d.ts","../../polling-controller/dist/types/staticintervalpollingcontroller.d.ts","../../polling-controller/dist/types/index.d.ts","../../gas-fee-controller/dist/types/gasfeecontroller.d.ts","../../gas-fee-controller/dist/types/index.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/mutexinterface.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/mutex.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/semaphoreinterface.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/semaphore.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/withtimeout.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/tryacquire.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/errors.d.ts","../../../node_modules/@metamask/nonce-tracker/node_modules/async-mutex/lib/index.d.ts","../../../node_modules/@metamask/nonce-tracker/dist/noncetracker.d.ts","../../../node_modules/@metamask/nonce-tracker/dist/index.d.ts","../../../node_modules/async-mutex/lib/mutexinterface.d.ts","../../../node_modules/async-mutex/lib/mutex.d.ts","../../../node_modules/async-mutex/lib/semaphoreinterface.d.ts","../../../node_modules/async-mutex/lib/semaphore.d.ts","../../../node_modules/async-mutex/lib/withtimeout.d.ts","../../../node_modules/async-mutex/lib/tryacquire.d.ts","../../../node_modules/async-mutex/lib/errors.d.ts","../../../node_modules/async-mutex/lib/index.d.ts","../../../node_modules/eth-method-registry/dist/index.d.ts","../../../node_modules/@types/lodash/common/common.d.ts","../../../node_modules/@types/lodash/common/array.d.ts","../../../node_modules/@types/lodash/common/collection.d.ts","../../../node_modules/@types/lodash/common/date.d.ts","../../../node_modules/@types/lodash/common/function.d.ts","../../../node_modules/@types/lodash/common/lang.d.ts","../../../node_modules/@types/lodash/common/math.d.ts","../../../node_modules/@types/lodash/common/number.d.ts","../../../node_modules/@types/lodash/common/object.d.ts","../../../node_modules/@types/lodash/common/seq.d.ts","../../../node_modules/@types/lodash/common/string.d.ts","../../../node_modules/@types/lodash/common/util.d.ts","../../../node_modules/@types/lodash/index.d.ts","../src/logger.ts","../../../node_modules/fast-json-patch/module/helpers.d.ts","../../../node_modules/fast-json-patch/module/core.d.ts","../../../node_modules/fast-json-patch/module/duplex.d.ts","../../../node_modules/fast-json-patch/index.d.ts","../src/types.ts","../src/utils/gas-flow.ts","../src/constants.ts","../src/utils/utils.ts","../src/utils/swaps.ts","../src/utils/gas-fees.ts","../src/gas-flows/defaultgasfeeflow.ts","../src/gas-flows/lineagasfeeflow.ts","../../../node_modules/@ethersproject/bytes/lib/index.d.ts","../../../node_modules/@ethersproject/bignumber/lib/bignumber.d.ts","../../../node_modules/@ethersproject/bignumber/lib/fixednumber.d.ts","../../../node_modules/@ethersproject/bignumber/lib/index.d.ts","../../../node_modules/@ethersproject/abi/lib/fragments.d.ts","../../../node_modules/@ethersproject/abi/lib/coders/abstract-coder.d.ts","../../../node_modules/@ethersproject/abi/lib/abi-coder.d.ts","../../../node_modules/@ethersproject/properties/lib/index.d.ts","../../../node_modules/@ethersproject/abi/lib/interface.d.ts","../../../node_modules/@ethersproject/abi/lib/index.d.ts","../../../node_modules/@ethersproject/networks/lib/types.d.ts","../../../node_modules/@ethersproject/networks/lib/index.d.ts","../../../node_modules/@ethersproject/transactions/lib/index.d.ts","../../../node_modules/@ethersproject/web/lib/index.d.ts","../../../node_modules/@ethersproject/abstract-provider/lib/index.d.ts","../../../node_modules/@ethersproject/abstract-signer/lib/index.d.ts","../../../node_modules/@ethersproject/contracts/lib/index.d.ts","../../../node_modules/@ethersproject/providers/lib/formatter.d.ts","../../../node_modules/@ethersproject/providers/lib/base-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/json-rpc-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/websocket-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/url-json-rpc-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/alchemy-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/ankr-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/cloudflare-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/etherscan-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/fallback-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/ipc-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/infura-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/json-rpc-batch-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/nodesmith-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/pocket-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/web3-provider.d.ts","../../../node_modules/@ethersproject/providers/lib/index.d.ts","../src/gas-flows/oraclelayer1gasfeeflow.ts","../src/gas-flows/optimismlayer1gasfeeflow.ts","../src/gas-flows/scrolllayer1gasfeeflow.ts","../src/gas-flows/testgasfeeflow.ts","../src/utils/etherscan.ts","../src/helpers/etherscanremotetransactionsource.ts","../src/utils/layer1-gas-fee-flow.ts","../src/helpers/gasfeepoller.ts","../src/helpers/incomingtransactionhelper.ts","../src/helpers/pendingtransactiontracker.ts","../src/helpers/multichaintrackinghelper.ts","../src/utils/external-transactions.ts","../src/utils/gas.ts","../src/utils/history.ts","../src/utils/nonce.ts","../../../node_modules/@metamask/metamask-eth-abis/dist/abis/abierc20.d.ts","../../../node_modules/@metamask/metamask-eth-abis/dist/abis/abierc721.d.ts","../../../node_modules/@metamask/metamask-eth-abis/dist/abis/abierc1155.d.ts","../../../node_modules/@metamask/metamask-eth-abis/dist/abis/fiattokenv2.d.ts","../../../node_modules/@metamask/metamask-eth-abis/dist/index.d.ts","../src/errors.ts","../src/utils/simulation-api.ts","../src/utils/simulation.ts","../src/utils/transaction-type.ts","../src/utils/validation.ts","../src/transactioncontroller.ts","../src/index.ts","../../../node_modules/@babel/types/lib/index.d.ts","../../../node_modules/@types/babel__generator/index.d.ts","../../../node_modules/@babel/parser/typings/babel-parser.d.ts","../../../node_modules/@types/babel__template/index.d.ts","../../../node_modules/@types/babel__traverse/index.d.ts","../../../node_modules/@types/babel__core/index.d.ts","../../../node_modules/@types/eslint/helpers.d.ts","../../../node_modules/@types/estree/index.d.ts","../../../node_modules/@types/json-schema/index.d.ts","../../../node_modules/@types/eslint/index.d.ts","../../../node_modules/@types/graceful-fs/index.d.ts","../../../node_modules/@types/istanbul-lib-coverage/index.d.ts","../../../node_modules/@types/istanbul-lib-report/index.d.ts","../../../node_modules/@types/istanbul-reports/index.d.ts","../../../node_modules/chalk/index.d.ts","../../../node_modules/jest-diff/build/cleanupsemantic.d.ts","../../../node_modules/pretty-format/build/types.d.ts","../../../node_modules/pretty-format/build/index.d.ts","../../../node_modules/jest-diff/build/types.d.ts","../../../node_modules/jest-diff/build/difflines.d.ts","../../../node_modules/jest-diff/build/printdiffs.d.ts","../../../node_modules/jest-diff/build/index.d.ts","../../../node_modules/jest-matcher-utils/build/index.d.ts","../../../node_modules/@types/jest/index.d.ts","../../../node_modules/@types/jest-when/index.d.ts","../../../node_modules/@types/json5/index.d.ts","../../../node_modules/@types/minimatch/index.d.ts","../../../node_modules/@types/parse-json/index.d.ts","../../../node_modules/@types/pbkdf2/index.d.ts","../../../node_modules/@types/prettier/index.d.ts","../../../node_modules/@types/secp256k1/index.d.ts","../../../node_modules/@types/semver/classes/semver.d.ts","../../../node_modules/@types/semver/functions/parse.d.ts","../../../node_modules/@types/semver/functions/valid.d.ts","../../../node_modules/@types/semver/functions/clean.d.ts","../../../node_modules/@types/semver/functions/inc.d.ts","../../../node_modules/@types/semver/functions/diff.d.ts","../../../node_modules/@types/semver/functions/major.d.ts","../../../node_modules/@types/semver/functions/minor.d.ts","../../../node_modules/@types/semver/functions/patch.d.ts","../../../node_modules/@types/semver/functions/prerelease.d.ts","../../../node_modules/@types/semver/functions/compare.d.ts","../../../node_modules/@types/semver/functions/rcompare.d.ts","../../../node_modules/@types/semver/functions/compare-loose.d.ts","../../../node_modules/@types/semver/functions/compare-build.d.ts","../../../node_modules/@types/semver/functions/sort.d.ts","../../../node_modules/@types/semver/functions/rsort.d.ts","../../../node_modules/@types/semver/functions/gt.d.ts","../../../node_modules/@types/semver/functions/lt.d.ts","../../../node_modules/@types/semver/functions/eq.d.ts","../../../node_modules/@types/semver/functions/neq.d.ts","../../../node_modules/@types/semver/functions/gte.d.ts","../../../node_modules/@types/semver/functions/lte.d.ts","../../../node_modules/@types/semver/functions/cmp.d.ts","../../../node_modules/@types/semver/functions/coerce.d.ts","../../../node_modules/@types/semver/classes/comparator.d.ts","../../../node_modules/@types/semver/classes/range.d.ts","../../../node_modules/@types/semver/functions/satisfies.d.ts","../../../node_modules/@types/semver/ranges/max-satisfying.d.ts","../../../node_modules/@types/semver/ranges/min-satisfying.d.ts","../../../node_modules/@types/semver/ranges/to-comparators.d.ts","../../../node_modules/@types/semver/ranges/min-version.d.ts","../../../node_modules/@types/semver/ranges/valid.d.ts","../../../node_modules/@types/semver/ranges/outside.d.ts","../../../node_modules/@types/semver/ranges/gtr.d.ts","../../../node_modules/@types/semver/ranges/ltr.d.ts","../../../node_modules/@types/semver/ranges/intersects.d.ts","../../../node_modules/@types/semver/ranges/simplify.d.ts","../../../node_modules/@types/semver/ranges/subset.d.ts","../../../node_modules/@types/semver/internals/identifiers.d.ts","../../../node_modules/@types/semver/index.d.ts","../../../node_modules/@types/sinonjs__fake-timers/index.d.ts","../../../node_modules/@types/sinon/index.d.ts","../../../node_modules/@types/stack-utils/index.d.ts","../../../node_modules/@types/yargs-parser/index.d.ts","../../../node_modules/@types/yargs/index.d.ts"],"fileInfos":[{"version":"8730f4bf322026ff5229336391a18bcaa1f94d4f82416c8b2f3954e2ccaae2ba","affectsGlobalScope":true},"dc47c4fa66b9b9890cf076304de2a9c5201e94b740cffdf09f87296d877d71f6","7a387c58583dfca701b6c85e0adaf43fb17d590fb16d5b2dc0a2fbd89f35c467","8a12173c586e95f4433e0c6dc446bc88346be73ffe9ca6eec7aa63c8f3dca7f9","5f4e733ced4e129482ae2186aae29fde948ab7182844c3a5a51dd346182c7b06","4b421cbfb3a38a27c279dec1e9112c3d1da296f77a1a85ddadf7e7a425d45d18","1fc5ab7a764205c68fa10d381b08417795fc73111d6dd16b5b1ed36badb743d9",{"version":"3aafcb693fe5b5c3bd277bd4c3a617b53db474fe498fc5df067c5603b1eebde7","affectsGlobalScope":true},{"version":"adb996790133eb33b33aadb9c09f15c2c575e71fb57a62de8bf74dbf59ec7dfb","affectsGlobalScope":true},{"version":"8cc8c5a3bac513368b0157f3d8b31cfdcfe78b56d3724f30f80ed9715e404af8","affectsGlobalScope":true},{"version":"cdccba9a388c2ee3fd6ad4018c640a471a6c060e96f1232062223063b0a5ac6a","affectsGlobalScope":true},{"version":"c5c05907c02476e4bde6b7e76a79ffcd948aedd14b6a8f56e4674221b0417398","affectsGlobalScope":true},{"version":"5f406584aef28a331c36523df688ca3650288d14f39c5d2e555c95f0d2ff8f6f","affectsGlobalScope":true},{"version":"22f230e544b35349cfb3bd9110b6ef37b41c6d6c43c3314a31bd0d9652fcec72","affectsGlobalScope":true},{"version":"7ea0b55f6b315cf9ac2ad622b0a7813315bb6e97bf4bb3fbf8f8affbca7dc695","affectsGlobalScope":true},{"version":"3013574108c36fd3aaca79764002b3717da09725a36a6fc02eac386593110f93","affectsGlobalScope":true},{"version":"eb26de841c52236d8222f87e9e6a235332e0788af8c87a71e9e210314300410a","affectsGlobalScope":true},{"version":"3be5a1453daa63e031d266bf342f3943603873d890ab8b9ada95e22389389006","affectsGlobalScope":true},{"version":"17bb1fc99591b00515502d264fa55dc8370c45c5298f4a5c2083557dccba5a2a","affectsGlobalScope":true},{"version":"7ce9f0bde3307ca1f944119f6365f2d776d281a393b576a18a2f2893a2d75c98","affectsGlobalScope":true},{"version":"6a6b173e739a6a99629a8594bfb294cc7329bfb7b227f12e1f7c11bc163b8577","affectsGlobalScope":true},{"version":"81cac4cbc92c0c839c70f8ffb94eb61e2d32dc1c3cf6d95844ca099463cf37ea","affectsGlobalScope":true},{"version":"b0124885ef82641903d232172577f2ceb5d3e60aed4da1153bab4221e1f6dd4e","affectsGlobalScope":true},{"version":"0eb85d6c590b0d577919a79e0084fa1744c1beba6fd0d4e951432fa1ede5510a","affectsGlobalScope":true},{"version":"da233fc1c8a377ba9e0bed690a73c290d843c2c3d23a7bd7ec5cd3d7d73ba1e0","affectsGlobalScope":true},{"version":"d154ea5bb7f7f9001ed9153e876b2d5b8f5c2bb9ec02b3ae0d239ec769f1f2ae","affectsGlobalScope":true},{"version":"bb2d3fb05a1d2ffbca947cc7cbc95d23e1d053d6595391bd325deb265a18d36c","affectsGlobalScope":true},{"version":"c80df75850fea5caa2afe43b9949338ce4e2de086f91713e9af1a06f973872b8","affectsGlobalScope":true},{"version":"9d57b2b5d15838ed094aa9ff1299eecef40b190722eb619bac4616657a05f951","affectsGlobalScope":true},{"version":"6c51b5dd26a2c31dbf37f00cfc32b2aa6a92e19c995aefb5b97a3a64f1ac99de","affectsGlobalScope":true},{"version":"6e7997ef61de3132e4d4b2250e75343f487903ddf5370e7ce33cf1b9db9a63ed","affectsGlobalScope":true},{"version":"2ad234885a4240522efccd77de6c7d99eecf9b4de0914adb9a35c0c22433f993","affectsGlobalScope":true},{"version":"5e5e095c4470c8bab227dbbc61374878ecead104c74ab9960d3adcccfee23205","affectsGlobalScope":true},{"version":"09aa50414b80c023553090e2f53827f007a301bc34b0495bfb2c3c08ab9ad1eb","affectsGlobalScope":true},{"version":"d7f680a43f8cd12a6b6122c07c54ba40952b0c8aa140dcfcf32eb9e6cb028596","affectsGlobalScope":true},{"version":"3787b83e297de7c315d55d4a7c546ae28e5f6c0a361b7a1dcec1f1f50a54ef11","affectsGlobalScope":true},{"version":"e7e8e1d368290e9295ef18ca23f405cf40d5456fa9f20db6373a61ca45f75f40","affectsGlobalScope":true},{"version":"faf0221ae0465363c842ce6aa8a0cbda5d9296940a8e26c86e04cc4081eea21e","affectsGlobalScope":true},{"version":"06393d13ea207a1bfe08ec8d7be562549c5e2da8983f2ee074e00002629d1871","affectsGlobalScope":true},{"version":"2768ef564cfc0689a1b76106c421a2909bdff0acbe87da010785adab80efdd5c","affectsGlobalScope":true},{"version":"b248e32ca52e8f5571390a4142558ae4f203ae2f94d5bac38a3084d529ef4e58","affectsGlobalScope":true},{"version":"52d1bb7ab7a3306fd0375c8bff560feed26ed676a5b0457fa8027b563aecb9a4","affectsGlobalScope":true},"70bbfaec021ac4a0c805374225b55d70887f987df8b8dd7711d79464bb7b4385","869089d60b67219f63e6aca810284c89bae1b384b5cbc7ce64e53d82ad223ed5",{"version":"f31113ac9492fdd6e78bf6151b338c92e5b1837be426ef4aa0648ce82d13b518","affectsGlobalScope":true},"62a0875a0397b35a2364f1d401c0ce17975dfa4d47bf6844de858ae04da349f9","ee7491d0318d1fafcba97d5b72b450eb52671570f7a4ecd9e8898d40eaae9472","e3e7d217d89b380c1f34395eadc9289542851b0f0a64007dfe1fb7cf7423d24e","fd79909e93b4d50fd0ed9f3d39ddf8ba0653290bac25c295aac49f6befbd081b","345a9cc2945406f53051cd0e9b51f82e1e53929848eab046fdda91ee8aa7da31","9debe2de883da37a914e5e784a7be54c201b8f1d783822ad6f443ff409a5ea21","dee5d5c5440cda1f3668f11809a5503c30db0476ad117dd450f7ba5a45300e8f","f5e396c1424c391078c866d6f84afe0b4d2f7f85a160b9c756cd63b5b1775d93","5caa6f4fff16066d377d4e254f6c34c16540da3809cd66cd626a303bc33c419f","730d055528bdf12c8524870bb33d237991be9084c57634e56e5d8075f6605e02","5b3cd03ae354ea96eff1f74d7c410fe4852e6382227e8b0ecf87ab5e3a5bbcd4","7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419",{"version":"056097110efd16869ec118cedb44ecbac9a019576eee808d61304ca6d5cb2cbe","affectsGlobalScope":true},"f51b4042a3ac86f1f707500a9768f88d0b0c1fc3f3e45a73333283dea720cdc6",{"version":"6fb8358e10ed92a7f515b7d79da3904c955a3ffd4e14aa9df6f0ea113041f1cf","affectsGlobalScope":true},"45c831238c6dac21c72da5f335747736a56a3847192bf03c84b958a7e9ec93e2","661a11d16ad2e3543a77c53bcd4017ee9a450f47ab7def3ab493a86eae4d550c",{"version":"8cdc646cec7819581ef343b83855b1bfe4fe674f2c84f4fb8dc90d82fb56bd3a","affectsGlobalScope":true},"a40826e8476694e90da94aa008283a7de50d1dafd37beada623863f1901cb7fb","9dd56225cc2d8cb8fe5ceb0043ff386987637e12fecc6078896058a99deae284","2375ed4b439215aa3b6d0c6fd175c78a4384b30cb43cbadaecbf0a18954c98cb","7693b90b3075deaccafd5efb467bf9f2b747a3075be888652ef73e64396d8628","41231da15bb5e3e806a8395bd15c7befd2ec90f9f4e3c9d0ae1356bccb76dbb0","fccfef201d057cb407fa515311bd608549bab6c7b8adcf8f2df31f5d3b796478",{"version":"ee1ee365d88c4c6c0c0a5a5701d66ebc27ccd0bcfcfaa482c6e2e7fe7b98edf7","affectsGlobalScope":true},"5f20d20b7607174caf1a6da9141aeb9f2142159ae2410ca30c7a0fccd1d19c99",{"version":"464762c6213566d072f1ced5e8e9a954785ec5e53883b7397198abb5ef5b8f71","affectsGlobalScope":true},"6387920dc3e18927335b086deec75bf8e50f879a5e273d32ee7bb7a55ba50572","9bba37424094688c4663c177a1379b229f919b8912889a472f32fdc5f08ddb4d","29a4be13b3a30d3e66667b75c58ec61fb2df8fa0422534fdee3cfb30c5dbf450","83366d901beda79d6eb37aaaf6ca248dcd88946302b2a7d975590783be51e88e","bf268a0aea37ad4ae3b7a9b58559190b6fc01ea16a31e35cd05817a0a60f895a","43ec77c369473e92e2ecebf0554a0fdaa9c256644a6070f28228dfcceec77351",{"version":"d7dad6db394a3d9f7b49755e4b610fbf8ed6eb0c9810ae5f1a119f6b5d76de45","affectsGlobalScope":true},"95ed02bacb4502c985b69742ec82a4576d4ff4a6620ecc91593f611d502ae546","bf755525c4e6f85a970b98c4755d98e8aa1b6dbd83a5d8fcc57d3d497351b936","dd67d2b5e4e8a182a38de8e69fb736945eaa4588e0909c14e01a14bd3cc1fd1e",{"version":"28084e15b63e6211769db2fe646d8bc5c4c6776321e0deffe2d12eefd52cb6b9","affectsGlobalScope":true},{"version":"aed37dabf86c99d6c8508700576ecede86688397bc12523541858705a0c737c2","affectsGlobalScope":true},"cc6ef5733d4ea6d2e06310a32dffd2c16418b467c5033d49cecc4f3a25de7497","94768454c3348b6ebe48e45fbad8c92e2bb7af4a35243edbe2b90823d0bd7f9a","0be79b3ff0f16b6c2f9bc8c4cc7097ea417d8d67f8267f7e1eec8e32b548c2ff","1c61ffa3a71b77363b30d19832c269ef62fba787f5610cac7254728d3b69ab2e","84da3c28344e621fd1d591f2c09e9595292d2b70018da28a553268ac122597d4","269929a24b2816343a178008ac9ae9248304d92a8ba8e233055e0ed6dbe6ef71","6e191fea1db6e9e4fa828259cf489e820ec9170effff57fb081a2f3295db4722","aed943465fbce1efe49ee16b5ea409050f15cd8eaf116f6fadb64ef0772e7d95","70d08483a67bf7050dbedace398ef3fee9f436fcd60517c97c4c1e22e3c6f3e8","c40fdf7b2e18df49ce0568e37f0292c12807a0748be79e272745e7216bed2606",{"version":"e933de8143e1d12dd51d89b398760fd5a9081896be366dad88a922d0b29f3c69","affectsGlobalScope":true},"4e228e78c1e9b0a75c70588d59288f63a6258e8b1fe4a67b0c53fe03461421d9","b38d55d08708c2410a3039687db70b4a5bfa69fc4845617c313b5a10d9c5c637","205d50c24359ead003dc537b9b65d2a64208dfdffe368f403cf9e0357831db9e","1265fddcd0c68be9d2a3b29805d0280484c961264dd95e0b675f7bd91f777e78",{"version":"a05e2d784c9be7051c4ac87a407c66d2106e23490c18c038bbd0712bde7602fd","affectsGlobalScope":true},{"version":"df90b9d0e9980762da8daf8adf6ffa0c853e76bfd269c377be0d07a9ad87acd2","affectsGlobalScope":true},"cf434b5c04792f62d6f4bdd5e2c8673f36e638e910333c172614d5def9b17f98","1d65d4798df9c2df008884035c41d3e67731f29db5ecb64cd7378797c7c53a2f","0faee6b555890a1cb106e2adc5d3ffd89545b1da894d474e9d436596d654998f","c6c01ea1c42508edf11a36d13b70f6e35774f74355ba5d358354d4a77cc67ea1","867f95abf1df444aab146b19847391fc2f922a55f6a970a27ed8226766cee29f",{"version":"ab9b9a36e5284fd8d3bf2f7d5fcbc60052f25f27e4d20954782099282c60d23e","affectsGlobalScope":true},"b0297b09e607bec9698cac7cf55463d6731406efb1161ee4d448293b47397c84","175323e2a79a6076e0bada8a390d535a3ea817158bf1b1f46e31efca9028a0a2","7a10053aadc19335532a4d02756db4865974fd69bea5439ddcc5bfdf062d9476","4967529644e391115ca5592184d4b63980569adf60ee685f968fd59ab1557188","aed9e712a9b168345362e8f3a949f16c99ca1e05d21328f05735dfdbb24414ef","b04fe6922ed3db93afdbd49cdda8576aa75f744592fceea96fb0d5f32158c4f5","ed8d6c8de90fc2a4faaebc28e91f2469928738efd5208fb75ade0fa607e892b7","d7c52b198d680fe65b1a8d1b001f0173ffa2536ca2e7082431d726ce1f6714cd","c07f251e1c4e415a838e5498380b55cfea94f3513229de292d2aa85ae52fc3e9","0ed401424892d6bf294a5374efe512d6951b54a71e5dd0290c55b6d0d915f6f7","b945be6da6a3616ef3a250bfe223362b1c7c6872e775b0c4d82a1bf7a28ff902","beea49237dd7c7110fabf3c7509919c9cb9da841d847c53cac162dc3479e2f87","0f45f8a529c450d8f394106cc622bff79e44a1716e1ac9c3cc68b43f7ecf65ee","c624ce90b04c27ce4f318ba6330d39bde3d4e306f0f497ce78d4bda5ab8e22ca","9b8253aa5cb2c82d505f72afdbf96e83b15cc6b9a6f4fadbbbab46210d5f1977","86a8f52e4b1ac49155e889376bcfa8528a634c90c27fec65aa0e949f77b740c5","aab5dd41c1e2316cc0b42a7dd15684f8582d5a1d16c0516276a2a8a7d0fecd9c","59948226626ee210045296ba1fc6cb0fe748d1ff613204e08e7157ab6862dee7","ec3e54d8b713c170fdc8110a7e4a6a97513a7ab6b05ac9e1100cb064d2bb7349","43beb30ecb39a603fde4376554887310b0699f25f7f39c5c91e3147b51bb3a26","666b77d7f06f49da114b090a399abbfa66d5b6c01a3fd9dc4f063a52ace28507","31997714a93fbc570f52d47d6a8ebfb021a34a68ea9ba58bbb69cdec9565657e","6032e4262822160128e644de3fc4410bcd7517c2f137525fd2623d2bb23cb0d3","8bd5c9b1016629c144fd228983395b9dbf0676a576716bc3d316cab612c33cd5","2ed90bd3925b23aed8f859ffd0e885250be0424ca2b57e9866dabef152e1d6b7","93f6bd17d92dab9db7897e1430a5aeaa03bcf51623156213d8397710367a76ce","3f62b770a42e8c47c7008726f95aa383e69d97e85e680d237b99fcb0ee601dd8","5b84cfe78028c35c3bb89c042f18bf08d09da11e82d275c378ae4d07d8477e6c","75b22c74010ba649de1a1676a4c4b8b5bb4294fecd05089e2094429b16d7840c","5615ccf831db2ffc82145243081ebdb60ea8e1005ee8f975d1c0c1401a9c894e","38682ed3630bb6ecdace80d5a9adc811fc20a419f1940446e306c3a020d083b9","cc182e6e4f691cd6f7bf7cb491247a4c7818f9f1cb2db1d45c65ff906e3f741b","a50599c08934a62f11657bdbe0dc929ab66da1b1f09974408fd9a33ec1bb8060","5a20e7d6c630b91be15e9b837853173829d00273197481dc8d3e94df61105a71","8d478048d71cc16f806d4b71b252ecb67c7444ccf4f4b09b29a312712184f859","e0eda929c6b9b628cdeb0e54cd3582cb97e64f28aab34612fc1431c545899584","9df4662ca3dbc2522bc115833ee04faa1afbb4e249a85ef4a0a09c621346bd08","b25d9065cf1c1f537a140bbc508e953ed2262f77134574c432d206ff36f4bdbf","1b103313097041aa9cd705a682c652f08613cb5cf8663321061c0902f845e81c","68ccec8662818911d8a12b8ed028bc5729fb4f1d34793c4701265ba60bc73cf4","5f85b8b79dc4d36af672c035b2beb71545de63a5d60bccbeee64c260941672ab","b3d48529ae61dc27d0bfbfa2cb3e0dff8189644bd155bdf5df1e8e14669f7043","40fe4b689225816b31fe5794c0fbf3534568819709e40295ead998a2bc1ab237","f65b5e33b9ad545a1eebbd6afe857314725ad42aaf069913e33f928ab3e4990a","fb6f2a87beb7fb1f4c2b762d0c76a9459fc91f557231569b0ee21399e22aa13d","31c858dc85996fac4b7fa944e1016d5c72f514930a72357ab5001097bf6511c7","3de30a871b3340be8b679c52aa12f90dd1c8c60874517be58968fdbcc4d79445","6fd985bd31eaf77542625306fb0404d32bff978990f0a06428e5f0b9a3b58109","980d21b0081cbf81774083b1e3a46f4bbdcd2b68858df0f66d7fad9c82bc34bc","68cc8d6fcc2f270d7108f02f3ebc59480a54615be3e09a47e14527f349e9d53e","3eb11dbf3489064a47a2e1cf9d261b1f100ef0b3b50ffca6c44dd99d6dd81ac1","b17f3bb7d8333479c7e45e5f3d876761b9bca58f97594eca3f6a944fd825e632","3c1f1236cce6d6e0c4e2c1b4371e6f72d7c14842ecd76a98ed0748ee5730c8f3","6d7f58d5ea72d7834946fd7104a734dc7d40661be8b2e1eaced1ddce3268ebaf","4c26222991e6c97d5a8f541d4f2c67585eda9e8b33cf9f52931b098045236e88","277983d414aa99d78655186c3ee1e1c38c302e336aff1d77b47fcdc39d8273fe","47383b45796d525a4039cd22d2840ac55a1ff03a43d027f7f867ba7314a9cf53","6548773b3abbc18de29176c2141f766d4e437e40596ee480447abf83575445ad","6ddd27af0436ce59dd4c1896e2bfdb2bdb2529847d078b83ce67a144dff05491","816264799aef3fd5a09a3b6c25217d5ec26a9dfc7465eac7d6073bcdc7d88f3f","4df0891b133884cd9ed752d31c7d0ec0a09234e9ed5394abffd3c660761598db","b603b62d3dcd31ef757dc7339b4fa8acdbca318b0fb9ac485f9a1351955615f9","e642bd47b75ad6b53cbf0dfd7ddfa0f120bd10193f0c58ec37d87b59bf604aca","be90b24d2ee6f875ce3aaa482e7c41a54278856b03d04212681c4032df62baf9","78f5ff400b3cb37e7b90eef1ff311253ed31c8cb66505e9828fad099bffde021","372c47090e1131305d163469a895ff2938f33fa73aad988df31cd31743f9efb6","71c67dc6987bdbd5599353f90009ff825dd7db0450ef9a0aee5bb0c574d18512","6f12403b5eca6ae7ca8e3efe3eeb9c683b06ce3e3844ccfd04098d83cd7e4957","282c535df88175d64d9df4550d2fd1176fd940c1c6822f1e7584003237f179d3","c3a4752cf103e4c6034d5bd449c8f9d5e7b352d22a5f8f9a41a8efb11646f9c2","11a9e38611ac3c77c74240c58b6bd64a0032128b29354e999650f1de1e034b1c","4ed103ca6fff9cb244f7c4b86d1eb28ce8069c32db720784329946731badb5bb","d738f282842970e058672663311c6875482ee36607c88b98ffb6604fba99cb2a","ec859cd8226aa623e41bbb47c249a55ee16dc1b8647359585244d57d3a5ed0c7","8891c6e959d253a66434ff5dc9ae46058fb3493e84b4ca39f710ef2d350656b1","c4463cf02535444dcbc3e67ecd29f1972490f74e49957d6fd4282a1013796ba6","0cb0a957ff02de0b25fd0f3f37130ca7f22d1e0dea256569c714c1f73c6791f8","2f5075dc512d51786b1ba3b1696565641dfaae3ac854f5f13d61fa12ef81a47e","ca3353cc82b1981f0d25d71d7432d583a6ef882ccdea82d65fbe49af37be51cb","50679a8e27aacf72f8c40bcab15d7ef5e83494089b4726b83eec4554344d5cdc","45351e0d51780b6f4088277a4457b9879506ee2720a887de232df0f1efcb33d8","e2d6963e7bf7186e30b7a4c9859aba4e96eda6d1be537e5b1a43bdddc7e9dc8f","10afdd7bba6ec9b7f95a4b419b2dbb64245fea4a61bbe7d68e2f841b414f7312","413121b26b3bd9f7fea237f15f564ee2b95bcd0cceec1b1621075375ccc0c0e0","d2af215963d01cef397ce8fa2f7ad08ee8beffdd39fe14b96021ddf26554b59f","2fc9848431d0f5e2b49bb312aaf07dd2d5a34300a2ced60200a2da49e6a82b43","c5ee2b685431ea2b9aacd9bb9e15cac1ecfa5c448972b188432313354d47c848","3e69be1137d88eb0730332aed359caedea4a27903da15dbe6a1615fa11206807","2283d079c3945b6e5ca8b9355311a213e03b74bffc65a3234c3c141a0a795700","f47272f05bd57f4356abc81232bded724d13e54f0fd801e0fb93a58237db1829","07ae8e9890f49ef6ebe629e339ac590025606a1e96754965bbb2bf889199ced2","d5c19655468e29f60c871b21e73af8ebc653f736e7123ade916f22c4a5f80ce5","6a8649609161e2794b383ba275b0a6cb4a072dde7b954648f83dc6cdf1bfe4a8","601d4a40a69c782addaf84185d4547568ec072095ab9976610d89922d1291f8b","d5c19655468e29f60c871b21e73af8ebc653f736e7123ade916f22c4a5f80ce5","b5c9c8c4a2cd1cb9f76d849fb472d475c3cebdd48306414a4a19bd11d82c4055","b61e6a808f5f50873ac03f35d5a38fa8d4dd23a24f80ab69df1a032e8c71562d","c8be9283a381044a392a0687af5d98d3f51cbada2320b1801a82c948b6e39499","85052c71d72b9b017c88179f57a464d66e22619c7acd7d83b117a79cf1608979","502cd7c30fe21e2c36b62913d0cb5d20affc8779b3ad40881b26d90a22de3aaa","6d3101b183ea67ef606b93fe42127f30b2db5ac3b72c34ca9d6d8b00eb85d0f6","f5d7a36ff056cc314b0f61c89a03c4c36a24183b246e61d958e75e86521304cd","ff30e8237e23dde68041b5f09526ee86835b12c5d8b6421c1153093fdbeb9438","f516fc1e77e5ffd71fbe705b679797c3c5eb76bf76a88549e6316a29f3e197f7","b5b1110565ac688b660a893654a6c1bce6747f3aa6f847001a8a5ff4412394ba","3a971ea3e36685b96f24fbd53a94ad8dc061711b84e51fde4cf201f7041e618d","9b6c162d20e2ad4abdcff61a24082564ac59e63092220618162aef6e440c9228","7804ff981554ba1a0592481072806fc39dc1484791beda43eb7a60e16e70a360","fcc8beef29f39f09b1d9c9f99c42f9fed605ab1c28d2a630185f732b9ba53763","d6e6620a30d582182acc3f0a992a0c311adc589f111096aea11ab83fc09a5ccc","6213b8f686f56beab22b59a0f468590fd3a4c5fa931236a017efeca91d7c9584","c451cec9a588b1f105a5ea2c6063d4fca112b9d70105cacdadda0e1ef67e9379","cb047832dc68f5a2c41c62c5e95ddcacbae3a8b034d40cd15319a8cb7f25104a","980336ccdfc3c08f3c3b201aa6662e6016e20f15847f8465b68f3e8e67b4665c","5a3493939995f46ff3d9073cd534fb8961c3bf4e08c71db27066ff03d906dea8","8f333214062532989f190aed5f99c62eb820722e41956e8229e17cd246fbdd10","d1f010c19eb9c8190bd0859fa3b6f4975543b912b8b85e20bbb0b5bfbdf4d2b3","de4ccc96cef3f97fab148640799abb32a24b567a902a8233913f98481e3131bf",{"version":"801934aa449fe6df584bccdcc5d5b9280295cb7ac84918b6014fc5086e6f9ff6","affectsGlobalScope":true},"5e379df3d61561c2ed7789b5995b9ba2143bbba21a905e2381e16efe7d1fa424","f07a137bbe2de7a122c37bfea00e761975fb264c49f18003d398d71b3fb35a5f","6af760fb9ea02dc807c5053d8aee86389c4fce72fbb26af7b9568cac6c4710d5","c62c4ba5e910b4523f7e7adf4a55ec45c2bac99d9d8e9b0fe0c2a800a6f641b9","92131434f876fdd6fcbc40bd54a9d7500c66974362b16bd42641f990468587f4","8cf023c0bd57992fdd2ce6a7030a1874f49c8edc62eaffa9bfffcf18d2a2a1a2","8ea8f3040e38fb50d7dc3653f3b8a0dbb5244e82111576f99ce096bdc0fbf94c","48ed788ad126545a6156fcc37cd3bcf17de18a3e3fe6b6ef62cfb8140d1a45a2","63c271a745f628ffd4bd7ad0a63b021c362c9bd6bf8b18441a7162892395a214","8d3457e6c7c5cb890729fb60cb8db18f261226a3ea3ff6a4db4b84ea78313ace","9f9e5bae412fa5909fae636d6733aee27a108cc2ed5b13980611016336774d3c","662fe197bba64bd3f17ee118058cd2d0d2dbe33d7c0c865fd6365d90bfc44e1e","030519c351f800551cac2658038804969ca4584d2c0175a710602ac234ca1340","0278a6939ca83cd040b08ff8c5fc7838b6693ddc52f22526bf158e6b10e0246c","c2d6206e5ba4fd3063b01218c2b3b997afc1cfbeb49fcee991fa8595842ce53d","6a8096993458a3d71229031aa7415974eb5b47b320213e29660adfb519d6a3f4","cb7996a1af5b1d276483cd0c9b9de6540eff021abc90a720511ff4464519a2ff","9df6ec68878d65bc690ea3a33ce3ef5aa8254c36bc5f8346c0c2fd1f3b88a35c","a4fad04c4acc8a4b195cbbccef4c55019104753d547d5c94441643ccc89108a0","0244c23ea642361f7c192c1f0cfff9c12cfa5f51f9b155edd5c0a89fef308d34","c7298e68632ab03155f6de963d3d09cc4a5874c28a81524f56c667d8a052e538","3c69a83bde847af6fc3a53e1bb6b13cd06d38a27a142814b8dacc374f3b93284","5b46f7113f54565e7ffc83f2b474f557a1f54c7e5946769d5be220454656be73","fb58035d39c5759283cb73cfb3548aefe370aa3ad4e81fdb4e46f0979eb7669f","1311c325948b2d5576cebc70b1bf968d3446b4630802bef54120daf04ce1f625","d0b3609e8e7afed0fd0570152255458407e67249b94f6603afdfd68599423f21","17f4c5a1d6eaa87ea27eadcdff9085af3190533d98f799dda79a3af6f9a630ea","3e6f734ddf40e2e99ff7fff9568b7d9720663af9a0632c26a352c8d3270a3f0e","ec13f78303abcf550c5569dfae1446b8ceb89050f68ce04491481e72e8122ae2","a3fc57dbaa7f1efb010399ad4ef4fd9b462aa4e93bf74a9a34b099b97ffcc9cb","ffddd7ec6a450b0cb6f2f73f80de1df963ead312d7c81a8440268f34146ecb87","5d6a36ca0087fd6876df654d1b4192f0e402adfde994ad47e5c065da33692f9c","eb157a09c5f543d98644e2a99a785f9e0e91f054f9fecbf1c3e15831ff5d63a7","edd5530e2b1ccdf65093296e40a8634fcb11ecda3c164c31383a8c34cb04bc9d","9dfaf96d090fe8d96143465d85b4837661ae535143eea9ef99cd20df2e66338e","209d45c27e03c1417c42985252de6c25a2ec23abdc199d88e6139c88b93abd11","0ee5cdba58cfde3012bb9ff2e9edcc4e35a651373a2aa2c83ff9eb7df635419a","540f4dca27ea5a232828b6d91e1b2fce2720bdabaa4c1f3fbf59b672cc58bd8a","ba086b99d545ec6c9ff356989f076b5652ea1b09bcc65b87dfc43a5195a2efcc","c85d9776b36166b928ab1488d9224ebf970d41b0a35f09a3ee0b9bee3e698061","683196f606c5dab1c8c4a24a66d26e00f16f2d4b2a5abe25ebedd37d2954f930","9c3a1b01cba1238fb723ce06b6c163ef6c53be755394406782564d5c42c636b2","6e795e6270d39e918c7a0e62ac73793cda06fcf4b3692ee46583e15f5bf57ab8","0e821ef1eb67fa6144ea4de4277d913f5b1982d7407afd5f93754a8239d41554","5c09195ef359ffa9c6bbdb4fefb101d87ede4b9e9c28213faf5b45d102e4c609","80b4d93a4dcc90a12f6f4bb7c6851a8182ae29e556716d0d80b5c012a5ef554a","2556ef9d1820e0b6bbca6dd65a50ea64f525c4d8247ab50dff44c3f0d14a5643","cbd1c836db190d6e3add07165afc228f04e1f6170e1fe3aa5e6fc24a7e9573a3","9b13881feb958237232586d888a10a39d47cdffe3ee34688ed41888fa7baad94","122fe82cf5af80f0b26832b258b537b7dfe3ec28449c301b259ab10204b50d45","c467dada8fea6d60dff8a8be2675f737cacc76e14e50b72daa0f0710376df84b","9cb80bba611c2dd155a446ce424fe4bb1df2129751bc9416b7e42c055d1ddbff","6ee568039016b81ed70292a595ab781ab978cba4243a5fe49507040ee4f7ac8a","043783bebe87efb440183c9ebc8c4fdc1bb92060a5a0f7ce847e30dee7013ac3","e3dc0a97a59dea936b4fb7b1f6f4117b4aac9c86d0cd08b69bab2d0532a8a5e3","5d897601f8a4fe913057019d8211b99b06e3138f625a0cfb601d074f4278271d","a68bb369c4ba8ab43a78f3fad2d3ec130e1418bc946521b9c84e9b336d6e88f1","65f219e6e1f9d27c677a49d41ae7989b83bf6baa56debbeb50d95c3ab21632e2","cfde5d194dd858ad68f910defaed5b0d28730f8bf38359a9265a93ab29bc7bef","c89354ae268153d965011e484150f0c92faa87f3f66507c25b496973178e0400","f20aae41b169cddcbf3fde8ac380443182c8d7225194e788c404d9e11e6dc75d","a6f4816a634bb1ceb513634c1ef7c0535f461ed2565336eed69f6ac2babbe15b","c48566cb13403fca44192b4528e3f2ac993869d39526bd42cd2f2167c0285add","efae20e0c581240c7522e04829da4f0453ca263068596554d4b0e27878c7dfac","3af68ef927788cda7daab34be513fa4508229fdc6e5130d564a0a1ccb3fefafe","bbbd2cbb15a37d5f4dd54ad8c7c537d3df8352117523030fcec7dcbe62a05a58","b50d24ebc117f8805332e7e260e9587f572bb7b2ff0ca1ff6cfafb38015781f3","5cc8b8e18fe7fefab4b3c53a39467b5a0deb4200abae7f063ff0624b9e856c51","8e990781eb0107c25429b1274a31a4f3866a9a46290cce40f354b2a6e71c6c21","608c45069e89c4c8f0ab29f896cc93c6553808072d6304b23611b6c6de3c24bb","22cbabe752781b5f35482af9d1fcf1455cb1ece74e8b84700d4abcb44abe3776","b9ce4613536386a98897f1e3d8f61a851ce6cb34dc3c9db4f2ef5f55f007e9e1","a5d1209c7bf277af86281392d46e12ce3dd6052586053f757fb2e606cc75c0f3","31b5f53e3d57470830e87f9e03c02d4569ac81d4a758fdda75092f9a3f58beba","d765fbab22fd7003a65ed670100362ec1c90d55a772e6773a774135594e7ea41","c1f11d9b42bfb0823d34d93c58df91ffb6690b5a717b7d310d83f258f1784e58","775b207f00d4df5b3b0b536aa696d572cdd2cabe8ea18dd28e8b52f691fa2a55","f75cd30f162c2af5e5aca39c01c1a521bfa034fae523793de872815a3468bc08","0cf1123db73dabd86466a462375a6addae52f58d23030c6033f8aadc23539a36","e29cef4158591ed213b1c2cba8988237b1ff369f7a6ecd8cb8ac0302bad1fba8","5307876e4d0021ea01235eb2f7c24671f3d8b37590f4b446cd132a4e1dc9a335","92550acd737790dc60c4c130e6aac78656dd48a8334a4882f40e7f86bdf7a590","3df821880914f8bb3c8107b1107be75c8ddbe2120a2cefabbaf9b65936b5f4dd","f46ba7c6fa7fcc8b3d57c4618c18db3f4d8bfe1fcab5551d7f6d9a82cf4d6078","078b7043bea0968860374bf4671ed74dd9f6be4e28ab659517d81f74be463c51","68b139ebb9a7f3ee4ded6286d74f978a47968727665120f3bfc560476ce33c4d","56d02c29b2fd39b1b1a1265df291f3f98e6ec3e6119aff9f4cfa44fe888efaa7","2d01884891da6495cb4a2f060e4898209a507e711464c4c1480df85264e863ed","c485c6497f7587314c4c4a59b74850cbca4c0c4bc08146a918cfd237ef821dbb","e9eec004735b1bf7015edf5400aeb914a53132134d230e93786590d904d094cc","080b1aa93227952b4dd74b9d2c6e4f6002eb8403533749116a1c53bb9961c02d","874087eec1d457f6e3baf5ac46c42ea200e55040b394fac667aa3a64c49f5f6c","6e8a5b04a18abb192abc89d7219b9c6f633cb3136777ec808673a65f111ca749","4e7ac7e5dd58a6c29c724728b031669e3068b194b62c2b83f92e76a36cb34dbb","d74d2a92b54f95e47d2b76bd5ee516aab7ae93afb79cd34c6681dd29eb09e72a","747e6326a724bc54f799a466a5b5c4978a601a04a063a5bdabe150af2f25b9e2","b57e22e53b56cca7a57bfcfb234aa6a66f9b9e4c07159d7388f94f17a3eaee2c","e47709ec4d1618ef429648cd8ef967aef2005526b34fcbfac33037add347dc71","b81abb3e47fbbb3af41fa75bada89bbcfa4b0feed9a0d6d4b19ed1ce1033b53c","15b330546e9784461058e5fd6e2346bf272140fa6f0cda34e193ae501d8b17b1","4d8ce72fd080bf9a46bdcc274bcbacccedd66d84e203966b197ac25a96932183","73327e6ae34e3f6591877fb75b451cf620cbbd76ee2b678213a9f793633cd0d3","3f1ba2f69944fa346789db7f60d53c9bec00032de0d797967978dea42e77b941","3f5df31539fee4816b97d4e45b4344fbdaf3ca59f6df941f8d780ee441e92cc1","50aaf44eb4d0e086af13729b3471a0a7dce95ea35ebd21c762ba26e203134b2e","3857c1773b8503c3ca45b7bc09ac89c3930c85ce93021054503f73d5d9101b5c","72702bd07fd6fb3ef64aadbcb909103aadfe71ee76e9fdeb11e0c92693cff6cb","f0dd6f7c9783637655478db7d7caf6becd41a79d54482aa59578ce88ab38e9bf",{"version":"cd756ccdabf433dd02b84d755383e489f14b3c1aede0477783aa04830fd5d695","affectsGlobalScope":true},"a4c88dbecdf8ee0c79f5b7c2bf31cd77e593f5d78384e2b674f67d754a549a9e","9cbdff04326da794ba008c0fc977ab062d1fe3fa2e9759654c72ffbe54b64a7c","aa60f8d20d36116fe05edaab24adee3c275209f71b65e272692cf99daf9489e1","150855f967a6490161d5aeed4cc4adf31fcb8f5dbe54b75799c12b8687fc9cc2","79576487ac18e047e8192fc582ff488ce375fe4df0cb028a17f831cf42b976f2","47ddb601df40bfa01cebdd06ee8b87d0b72aa1259a4ceba3ad3b5cf68130112a","6b6392704ddb3f50e647dbbb716782bdd0cf8ea9cc134aae256a26223e632b47","afc3ad2a50f7f4de908e26fcf467e09ab8528c0e90f91e602b4865d953839228","df90b0c6b1d81851364c4d97fa23b91a993482bcf4a7bed7c7a24aa41632d494","db34610570eed46b8b72bc662a91261200b8578af0ac02781ce7d9aca99bc683","11ee9ab699b4619d217c640d917ca198f58066a86bd58c2917197d62aa6601e0","cf9d589d9e73bf32c8e7a6cae6b4a1cf9bef39e5594072533fdce985581a6ddc","959544feb1ca2df29eec6c500f27ea10f4885df245ebd8418fb4b87914614383","6548ab4b57eb9d092471a04513091673345f2fd95d5b876f600402ea8d603ee0","2793e8c6a023d26f78d6777a6d7f20fae3a9a8169863d46d8d54c73071851232","d0f11e830aa1350a31d9c00a0197243e9711e4882947aef53a96c629f405cb10","6610b9f45f1f71d2b1fb67df49cbcabe3f9e668a1ccb7d8328a51407b259ffb3","abbcc437e0792ab2fe08797ceca1ec85a95ec413c51612313b18ab8e75f690f6","e29d76ef1183ac0edf94b4712b6e51730c447c7e773e75ceb44a720b0c9a9fd9","4ee6dc3424998eede9a2a9b114acaaf7969cdda67baf82ba2c9cf88a8eec0ab1","8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","25139d6a726e0e19d9fc4fa3197367b4a82ec34a08a5ecf23963e142c202c0f3","e3328bffc8eab74665a4fe9c59d6f12f4c8570c3d858497e241eb37efe17dfcf","29389551e426a46421134b55182d6fcf5b143670998bf81db2619c1228235392","c18f7e16982695bdd04e3e183a327d116185f77f1a37b9b2e849d7d93269cd74","2cfb37011989c21dc70b91d521a2d5a4e0f18507f5f536b5dfe504edb15916e8","bb5e02df7aaec7a4ea642639a9963b24b8d9fd6798351f07d8c58616942fbcbf","299a899cb4d061f5d83843ec453e936e9659b2c435746823f90c40eddaef4745","d5610c0fd12870f644b0f42c1bcc4fa2295ac3e3ca01916bdb42c3bdc4c80c36","2c56a8e249b1f45dbdf973100cd37fe2ea68709573cf1fdf2e3052c593be68d8","3553da417ee7b07e388b13bd12a70a1c03e65a6132ba5427fe68f5b362373e6f","612358502042d351c227ba779fdcf6d875d827e424930e60297c533524e50668","d2b5be376ef162aa0c24a826e7dd2d77671a045c085e16d1c1276db4bdccbac7","c4138d8dcccedaff6621e009cf0a54a7bed2a5ad4c509a3513bccc4f417ef939","ad8747fe978dff3e80f4b12b48d37cc8dff11b61d04c035aefbc982ce21201ce","b154f789fd65298e1ba6cbba6944ea892d564c95f3d3700ed85baf8f80748473","c660265aedd7c5b236e2017e53095cb98da66200eb0e8d023b5bf713c36494e8","0efc36bf5c0daca6217fec7063359ccdab8c3a23bb405d25340fae22cf72d74f","5abff0c87d4f9c89715107042d4c73b68ef7a128759f451c8a0fc450cbaaf660","5a03308fbd1af441065149a84c692931bebc7e7735afc23be8684f4e10d3aa06","c787bf4f8f0abbf815cfbd348be41046f2b8f270be24fe7aa8a8fcdd2b7df8c2","e7a5191c663a3228f30104961d548b372e51c5936c01ffc8eddd262bb98d7d7c","43fdc9abe6f8640fda4cdc55a1ee5f666d3fce554277043df925c383137ddf69","f0b09665c9d52de465687fbd3cfb65111d3ffc59ae00c6f42654150f3db05518","72f8c078d06cff690e24ff2b0e118a9de2833dcebf7c53e762dcb505ddf36a68","9705efb0fd901180de84ca4dd11d86f87fd73f99d6a5660a664c048a7487e385","f9b9d0950fdfb90f57e3f045fe73dce7fa6e7921b37622fc12e64fcd90afbd0f","e61b36e7fde608f8bb4b9c973d81556553a715eaef42a181a16ddd7a28da4ac7","03b8389b222af729eae0fb3c33366dcbb1f5a0102ce319bf1d7d5ee987e59fd0","2bf6be7c04db280fdd9b786764f8650c23f9f4d533791cb25a11b25314b76a55","dbb5fc7edd36bfba95cc4dd564e4458276ced30eed18bc05fbda948b3fda8686","c2b556c7cff0dabce2e31cb373ac61c14d8ebc35f1086dff30b39e9ec5357d0d","f958af01131076e8af55d28c4835a51063226ab488ca8738fdee38aeef7d0d33","9f3797b01e3d83d4e4b875699ae984f380ca86aa0a0c9df43ac5bba1cb1f8b7b","752b15ad1b34887adeaa838fc55f5d4ca399026afd266d4ed4db0e3db02eae4e","778331eaea1093451e50be9844bd2b6937c3bb81b0b1ee700624c9774ecfcf2b","0ca0dfc9f657d0822eca9530c7870b22a1d2a5fc48182bdd4d0e6e88e4ad9c35","5c746f034288e6842dd1589b169dcfcc16c5ce5abbd928889ab67aea4fe0b501","92ce6dbbcc135cffd09a58e19fef34bf351391bec92c40d849e4e9997d475769","99e77d092fed72b6b8578d00c7af004f76e98b30ba99f1947535eb4c04a51676","b5ef52a9f9083724decc5d060f0b34e3a480deed71c32d55ca16c214eb4cc928","5d3d7938b2d7d0a9f851276741327c2ae4c013e7eb420fc3f7caed3b79c8f37f","14df6b81e50a035e9e391558cf30a0420d03e2eb42c7db9c57f44b818e5d5179","f100912a3785eed4a3d29c12f5910b101af9353454de5ddba9b4d43456c56dd1","446439eacf81a163fd7dfc53b28f80deca3d13b250d67639739aa25aa4491090","98034cd285344125f7165a3bb68246d38ab35fabe7f6d6a7c8f80407d31f548d","06b4a23064991251512df4edc12341d5bc69a17b942da18372312d383c90eee7","0f898802705f9a534b537f1be6c57265080e0abd6993d935554c255e6d56cc1a","745efa7b6e27b7216cccede166a822b56acc41b10a8090966c8cf2c96239cb83","6ab2a6257ae7bb05559841100c786c845fe465a90be7b904db9096c2fb14696b","26958d6f77e6db2425ca65df0fbfaba439396ef7f4457f5643fc32e4b62568a6","5d697a4b315cc5bb3042ae869abffd10c3b0d7b182cda0e4c45d8819937e5796","89b040dec8fcfc1de98827e1f4d4977e6ff5d3302c6790e9f10b54b916e1c742","6ee58aa536dabb19b09bc036f1abe83feb51e13d63b23d30b2d0631a2de99b8f","8aceb205dcc6f814ad99635baf1e40b6e01d06d3fe27b72fd766c6d0b8c0c600","299567f84bfedd1468dca2755a829cb19e607a6811673788807dc8921e211bc9","795d9fb85aad92221504db74dd179b506bd189bba0c104426f7e7bb8a66ffee5","1311bc194e0a69fe61031e852c1c0b439e2a2a3d1d5e2d8ff795499b9f283459","4b7ce19369d7e7fae76720c2c6c7f671bf3fa0f7093edb864f1ac358ca7c456c","c972ef44deca1fa8fab465915ffa00f82e126aacf3dfc8979c03b1b066ce5bb6","30285a1011c6d6b52f3ba3abb0a984be8148c05cdefb8eb6eb562335a3991f35","e0de9f50e80fed1cc161b50e8e68dc056e38df75a4ef667a06b1922e372de169","6a8b31be08b212d1fc96de0ddd1ea49f32382ba712fea24c70bb56447f643f82","19ac6d624e4c18de4584db4bbdbc55387dbe3d19b3c134e50346bdf165658a17","54e3798c2801e8f3bc7a825d3d26c6a80ce763e19e6cb0b714594c430ef72332","70b8333214aadaccda8d38435911d3e3a686e503837dfda6b8c3f8c83e05729b","fe849e916564b8172f31a547395516668f3c122bfe017f82e7140d8dac402208","d42c6e985bdb10a2aaa3dae14d9b0d8589e74a7c2f9475bf543b855bb3c010ba","56c48fb5bb6316dfc27fbad065966b4ddbc38e9a0a1a5060d19b5da405ae7d6e","7091568b9a1b74b699ad09df6c130db712ed089d173a235e301a7a7ee0a4ca44","de33aa2a38affd9e71297ef7ec001a4525502878b09744308fb6518159f77d2d","57476e482c9b4e152bd23d0dc3c29375e48afee0de775674a3c1ea63cb4cf843","3ec4ecf6502ebdb1f3e24c712eb70160c606214ba2e71b4304b5a50fc2e4f293","83f7b6c1dc91deece32c3bee746a43f3616b7cc9f6510764bd53451f6712ff25","c23f2e8772304163fa7e4335be11f3dbdfd720d2209057566b7dfef746ef1862","2a26cb78d3de9708cd656787a663902270c9421ef89188286c3b7ec89b63bb15","e61fda2800677c210116c397dd85079a0956c87fd714826c08b25b10fdd56546","ef7bdfb4f157f9c9b9bd7f5766f0f8e07fac8e7482eec071673f3c9d08082982","d2f2ac1436cbb7c8d122cc7de96521345254e5b36591d9d064d9763de2a7b254","3cd2ba07285d01224f9595924dc7f760c7babb386a6eb825cb551f8d829fe6fa","3ae9770861c2ece5849778e9f15567d95b87df0165c0a5b1312181df19458a56","37b51656ff8302a4556e29c775f311eb9ad813948d2c527405cea041dba3baf3","00abf32ca3af92f8be9ecbc9b63090b4909a756317d791927a83cffd24e9c8ac","cd28efe88fac7a92f3f5cfc7dd3c764f0b31bdaaa061ff044de1639810d6a7da","8b2100d3ba68063b7baf5038f26eefe46543dcebf1e7dbaf46277f24307cefcb","131b7f32092aa78e12fcb2a6db7c71e17f85e076c0635ad8d991b80d10130c19","d1c84af1e6d5fa4a5f4badd45b03b67c9255a675df235a3ec25307a0f5524278","aa4d6dc9282133162a76109d99c5795583276c4fd27284f128d484acf12b0841","3355c4c572f076ad963d95f0e28075b8558e2ab492c84eb94f9e2c48f1c2368b","5638cfd48b0c56bc9ed0c779d53a40b92c9cd9c9d6312e3a21c52542d38094f3","827eb54656695635a6e25543f711f0fe86d1083e5e1c0e84f394ffc122bd3ad7","2309cee540edc190aa607149b673b437cb8807f4e8d921bf7f5a50e6aa8d609c","703509e96cc30dce834ef8188c958c69306473b8a7e5cb3a6f324cee05a1f7bb","900daf04dc607dc3858c0f976d6f9e17b829a07de58d62dc6f730eaf06986075","08e0ac95e650bd4c87145b6ab2257b70c06254bf76a0b9f8a7d60c51fb8ed6b8","4b57ec505a035491c692b89af2c6902c312ec22f8fa9b6dae3e93686659fb7e0","7d796672940d3b2d37f2edea4d7bcf4c7993966286006228cbc8fa35ac92871d","132fd53917ed7f55275faa52c35e4d4d41e9576fea231d12740b723df2bade93","de2ecf9b1d6f60338f7b59b6f593ef77af9abd0e70ba8f2942953d0c6e1850af","cf18e9d003f1d3d1d61a04eb2d1cff3e8a8cf9cd306d0532ea82700069f2fc42","393192a39f26f9247a74ecbaea6668972af8e9125c955d1798234dceca6010f7","27ca878cf70b3030e8403f51ce65949d364fa776d6dae3527f91635a40836672","178e2de7a8702742957ad24deaeddec84a48cd913b5d932b16afd2a707b3e416","a45ee7555d019a67fbe092898d1aef0b1d02a9f6679ab84461ff515b4460d706","29c188a2c660f99f1b4835022e011c4268d7af989d4b7dda33c0a69ca1a777f8","1ed0bf138e87912d741e28333b58cbf814ae863783b3b404d2454cbabb9c5fc0","3452ee7d8ef0b1bbd47b2a56924a1dc3c79dc84a19d212e9dc496f92e4943aa0","8c95f96ccd4be0674944077aec1e4f2cccd515ca06d4327562dd017250e7d3fc","6fe7571c8a80808224648046008d1366ba4e29206ac79ce4c56d6fab3350492b","a98be76d8c257aa9e316bdb305b8c4228f0cf904d4b70547fc2999f3f99b5a01","7419d99dfe020d543c8ee736ab7ec17127d6a2c61c40e5f245c6dbd3fa6eaea4","2495815b16258136f98d91e441f4462f9b694520af86bb8c8373724cdc410096","a64568c16a5821575de4f6280ba1ea4686a1ceecd649fa90ba957c8b1b007013","ac46f284c80582f7c1284eef93f2d1c80add2d3b0e8a4076d6ca3db58d3af747","dee4dbaef83bb1061a44f39a91a59300d3dc02528eb57f748222235dd8e02159","a39c32b055d2e6103e5c49b9aed2d7bb5b06571c98fc31105264d280431bdbd7","618ebb93311695a13844118cdc9a7314dd3a2c6f35092d87f76828cac555ddc9","d36c3d116ce59a3f072c0014f0c020c76e916ba906066ddc4f193f546a43bceb","9bed8447acaa89be63540ec500b165442fcb0de020015175b5a5c66d42a61c4a","f128a2d1209d243ba2f7755c2fc313be2c7569fa0d9b4dc5cc60714fb0cc6634","a17e6861b709149f29a2bd896cee94526df2f06b24a2b60614b56649b5e9aabe","9c79ace686f720f4dd833740f7190e12cdce363362c982c164745527a412ef40","439850ca5075c6db55487b2c7fb27a6051fecbf180eee0809b67bb2783a89813","75d48857bc4216880443a24d985071262bb8b89a9952c77fd430cb0caa21f9bf","33e40cf77499b3d9712db82e15683373925e85817dbe82a24ee0ee6e44bffb70","d5bbd453310990e851908183fbbef9e6e2db8e0c86d97b42b723fd5238f71c81","95e76bed30f6e993e1fcc1b90a4675682e4800ae43403547a775d6e3c7ab2b0f","8b206b995edc6dd849b85c1c56531b9780e3ba75302fd02a2d173f008028707e","97040b190f0daa10cf9a15e51a2fac66b26ddefd7b65998bd6027d1dd67647b7","877c25dfae100e555014e45d1d80364496a0c876201e5dea91a0fd0a6a4ff765","d53f9f96afd41359edeb2d5ad98559f3bfad261391d5aef95320fefb0c6a8742","23d98226adf3be74e1f0470f85e7fd154cd7aa979d60b43190a7437f0d0426eb","639f9321a98b734242a3573764d7f1de5369b0b0b10c768ae37639e8bda5dd03","a42c39d8b7d1b1eccb69c7919ea60dcc2670ea672a0af90b70a730974ec0e9fb","dc5fe5f6b39c3fdfaeba333bcd5f0cc98bb3068797a4d7010f585366f549ddf7","4a3ab8cb278bfd1f18f24cc45a02188b63afa6aef50035df6d79c4638f24059a","e724c9ce92f2a8a31ed260764c5455852a13d292e2a31d26acc6840ec0e83208","40220ba1b091aff0cb20df5467202b62af561b09fcf3b24c22a60066d46f9e62","30abf588759f9e828a94f0c7f031eae094bb668c6dd4d902fa296779267c05c5","bd875d031474860131eadb42300aa57a71527bbb2b239d5b31ab6a9e352c84f0","773bf9af93b5027de9b5b4c779d5cda35f0eb92c7f43a97f2ef3ca081495a191","617f2b4f5115969c7b0f225d4962e6bec1cec7e5c687d84370eba4931b7dd047","59625b1fcc91f2686751fd5b623126f434d7b405bd8d866a555963ce2ac69846","5e0dc1bd24b45c46f2188d2f7f4b67f311610c72b706f963c5bf04c2e1fcc35d","fc69ffd599d3e525aba38f80c7cc2ecd187dbf148287364c75f199c8294a00e6","2ad138be6972de52ed966e6402aa6403af79e9f183486e0a725ffa075a0555fb","480274a4f75a7b3bd5c697a55e1905887b62a928592c0db3c282525fb235ba70","967fb6e86b55db228ab50c81f85f39d6a23a0c15bcfa6e19d255e0952d33a65a","c39e7d32dddfcdaa93b18b99fa430ebb1d6ba366459563d400add22f92e3644b","e3932de252bbe43132ad3226865b2a376ad945dbc1d767540c01b7bddc6477c2","b2f52f3cbd863dc4e690614b5cddbf412dea435d0de099db6d8adfd3cbefcd65","557c93b35f3b58e6844a9b8817559da1e0641f7f08f918e3cd1a8efee126746f","80ad2ae93d57dadac5e377ec6743df5e0211ea30bafd4b648c52366af057bb2b","07f90213b5800a0b43a6d6f309517dcca5afc6ffeb4bed396878a29fc5d6ceb0","bb0e637020f81cb40d16f202c3a783f0e269e29547fb84ca9f187a5ea8556965","462da802b50ac0d94a3c8f7f58a6a0aa08108bfc1394449ea56f1e0f63f5132e","2ccea88888048bbfcacbc9531a5596ea48a3e7dcd0a25f531a81bb717903ba4f","b7eece07762a9a944f097ee05d6f6b642b1e2dd87e6fc1b09600d881e5475377","1916218868966583a3c9f18501ee78929cab8450ebb8076ebd609873c258154d","98ca5ae10ab02fe747a7a53138f43525e0129aa1107892ea4e1fe9c99575809c","9760678d20c9faa0d0e1269806bce578bb76598a4a188a4d3987171263be20c5","21f706150e32f03ecd1714d7a7ac55ce3caadc7c7a2a960ba57cc5d39ad84c9d","6954ec87361b77bb8895426909fecfd154e3fd72a2b82f681c8bb15bc46f2389","da1963f37d566ff9f71bf8ca5c628656bae02fc9509050041547e9c7063cc58f","57e4bed825036f7f1328505bc512af492f28b1b57a48f1ff9b6d90b930041a52","3ef0957915b7719ac58153eaea6ce810ff8688276e570f8938455f3ec7930df7","05e0ad043fdd4e2d4874a97bd716174af64d63e43851c09830c00e819a80d395","2dff0ed1eb2046fbdbc2c13914117e1ff1112e217f90542ea5e7f41e39f0393e","a0ba1e2711c2520189ed980225e7a429b0706a1eabf9113e53f0e72550a1b23d","169b66aee819a4b165c397b832b31691f0be8d35cf8f2ec6364c23ee727b20b8","badb4cfbfc6eca3a038be22c76297bec0b5c1478d8b73d60e8b50725b7dcc15c","21e7e0eddddc112f2b891d1066eac74680291db768d3ef9b908965935380ab98","489e195150979dc291520e6f3289f055516cf342f314931c6b4553aebf2859bb","516efe800aaa0b7504b71f2d7e7e9bed5f28eb6c9c739bfdf237f09c7addea46","10ae729013e6620dc937df5dd7077c34e29ad313a28aa75cec39957640cdc8b0","ac5f95dee5e4787fa7c68a81a052cdfa0e03adec8331d3276389384df36cb849","0aaa321f1f662ec931e55c85867d316d8af16b59337111e22901516a0e1caacb","fab58e600970e66547644a44bc9918e3223aa2cbd9e8763cec004b2cfb48827e","a120dfb4736e6ec4c78f1bff5ff7f977d346152e6b7020659ee1ce4717f6f66f","9eda7b58498bed72dd98ebf1d6f8dd3bf5df5004b2f91c610093bf48f970c615","8e7adb22c0adecf7464861fc58ae3fc617b41ffbd70c97aa8493dc0966a82273","755f3cd1d9c1b564cff090e3b0e29200ae55690a91b87cb9e7a64c2dbeb314d3","d6bb7e0a6877b7856c183bff13d09dd9ae599ea43c6f6b33d3d5f72a830ed460","f1b51ae93c762d7c43f559933cd4842dd870367e8d92e90704ffa685dd5b29a3","3f450762fd7c34ed545e738abccb0af6a703572a10521643cf8fc88e3724c99c","bf5d041f2440b4a9391e2b5eb3b8d94cbf1e3b8ff4703b6539d4e65e758c8f37","8516469eb90e723b0eb03df1be098f7e6a4709f6f48fd4532868d20a0a934f6e","d60e9ab369a72d234aac49adbe2900d8ef1408a6ea4db552cf2a48c9d8d6a1bc","0ebb4698803f01e2e7df6acce572fff068f4a20c47221721dafd70a27e372831","03460a54d0e0481d1e11097f66ad43f054bc95efdafe5f81bbc7a82be181af75","ded24ddc7157689a5aa14bd651272ab8cd6e7812da2196a65d8c5e63131cfb23","2cea9689efa8591732096235abe7f084fc29c92badd5b0897a5e876b77e71887","4ed4e504126014fee13aaef5e3fc140f2ff7031ff3a8b5386717905820ea2d09","00e77e0bf106bc1e4f303ab02724df5173506d44acb6c22b4f582a88f22c3250","30d2170e1a718b5035611af55e3618b4ba8f42f0749bb52ee593da6082c4e2ce","568c86c9edf716ae08cd3c8ca61647a3eb43ff52a9aeb7c972f7be62cd35b797","a3b8b6be7620897d1e481e8650c980a210a138fceb6e710eaf95fd9dd0dfe94a","12c89d0e32758c120a569045f21cf5b77244f86792611ced8de7f86b37e77781","14bd47270e654c8eb3b1489fa8c095912ee62a0a29bb92743393203722347c53","cc8b411aec64e03abfc3936a397025c781adb89942ec2fcc66e2a353f93ce677","db5624ecf400ed47648e72353a0ebefd3293d2e6295834a3f013c548ecbd0edf","92cb686a9ca5eb5dd7d5d8d43a3707194c1e91ea07a027b3bcb60b6011b24632","da3ab7396ab4fe390f01091bd0d4c4a4e1e2a15a46d47446d6fb7194897d0f6c","66bbae6120d307ec2021ebd2241b8ad23f832b663e13363ca8b4c8dbc131a4e6","fb14266ae4070bd16db6b071e98887452bc359695c40742e38515a89dbc80a63","4a24d83c0d8f489465c4d38ed9fd87121c8a2cf50c47efe09c2eca93d39fa908","c052e32b9de53cd2596f196a0901801961bd7a31be9fac4ac2f117e4103e3a07","b15cdbb45919bc3b8e6b6f962d65382e85061d70bc26a968604f3dce4ad3a891","d6b58d955981bc1742501b792f1ab9f4cba0c4611f28dcf1c99376c1c33c9f9c","f0b9f6d5db82c3d1679f71b187c4451dbc2875ba734ce416a4804ad47390970a","a5c38939c3e22954a7166d80ab931ac6757283737b000f1e6dc924c6f4402b88","31a863da9da2a3edec16665695bdbc3134e853195f82dafec58e98c8e1bb3119","a00417f73bbba413d1345dd77252ede0bd0c957e37a9cadc9abb4c34cbd0eac1","90d1ad8d2983cb003d6f237b41c56a8f252f72071bbc53576e02b3c96d7ea47a","f3815045e126ec1b9d224782805a915ae01876a1c7d1eb9b3e320ffadbd63535","d07557f21b2ad690bfe37864aa28090bd7d01c7152b77938d92d97c8419c7144","b843ea5227a9873512aa1226b546a7e52ea5e922b89461f8b202a2f2a3f0b013","64b4d440f905da272e0568224ef8d62c5cd730755c6d453043f2e606e060ec5a","d6b58d955981bc1742501b792f1ab9f4cba0c4611f28dcf1c99376c1c33c9f9c","f0b9f6d5db82c3d1679f71b187c4451dbc2875ba734ce416a4804ad47390970a","a5c38939c3e22954a7166d80ab931ac6757283737b000f1e6dc924c6f4402b88","31a863da9da2a3edec16665695bdbc3134e853195f82dafec58e98c8e1bb3119","c0e03327bc548757709a7e2ca3063ca8b46227b5e13cd981ca3483035ef5ac44","b8442e9db28157344d1bc5d8a5a256f1692de213f0c0ddeb84359834015a008c","458111fc89d11d2151277c822dfdc1a28fa5b6b2493cf942e37d4cd0a6ee5f22","da2b6356b84a40111aaecb18304ea4e4fcb43d70efb1c13ca7d7a906445ee0d3","187119ff4f9553676a884e296089e131e8cc01691c546273b1d0089c3533ce42","febf0b2de54781102b00f61653b21377390a048fbf5262718c91860d11ff34a6","6f294731b495c65ecf46a5694f0082954b961cf05463bea823f8014098eaffa0","0aaef8cded245bf5036a7a40b65622dd6c4da71f7a35343112edbe112b348a1e","00baffbe8a2f2e4875367479489b5d43b5fc1429ecb4a4cc98cfc3009095f52a","68a0d0c508e1b6d8d23a519a8a0a3303dc5baa4849ca049f21e5bad41945e3fc","3c92b6dfd43cc1c2485d9eba5ff0b74a19bb8725b692773ef1d66dac48cda4bd","b03afe4bec768ae333582915146f48b161e567a81b5ebc31c4d78af089770ac9","df996e25faa505f85aeb294d15ebe61b399cf1d1e49959cdfaf2cc0815c203f9","4f6a12044ee6f458db11964153830abbc499e73d065c51c329ec97407f4b13dd",{"version":"99e8bb8d262bece129ac203f0c7436a07771e9cf5ba06a308d1b16993606eaf2","signature":"8705a9680ed4afb15edbd7bb9ee24af33060d1165117f293559f3073bf8d0101"},"ebf6e19cb84d78da20d022a95f05e8aef12e56f816a1ee12835a4da40d7b14cf","589357c2f88f1188a0dfc48c4c4cf4d22fac9f654805df5f2789a01b5616b74f","6abe62ec5b9b6a747c1a7687d58ff179cdfb61adee717b6e4882120f7da4399f","5c1301f550be26133f4fd34eadf38815db096ecaf9b75948b444a063097f496d",{"version":"26e64fa5fc9c7fce9daf4131f396fb5012dbdd92fb2e2bcda5aa083a76d18888","signature":"cdca22d444beb7cbe168d11a666b994be4b19c5ed7df1856612ac4dd7c2242fe"},{"version":"34ef3dd636b7074beec81346987a81ac245e1cfd75adf0babc68e6cb6c572ca3","signature":"82065c62b6a8089452cb40191a55299b2d0718ddce833446faa6c01f48f05b29"},{"version":"c1eb1aa5e32fd31d4564bffb458942d8caf500d86388c811cbb853c274e4773a","signature":"a7fe41f597b2631d3fb439d9b3ee32d1606c651a45ce2fa0d170a2614e68d280"},{"version":"327fd9ca522780f73a64e32e400a6c5bcdd89a5e706314d57ff1611bf1a99a0d","signature":"70b3082385b926b4bb0dbcef0b2f444c4f807d312546f27ee248d50b0dfa5877"},{"version":"3b1ea19c2b95501c5d8e87fe4c8044d204c4402a8b48f282bd348f973355f3c5","signature":"01b86f9481ddaf74b65f12e90ae2d5bedbc0e67e64e8cb273c7a1907cc66dbec"},{"version":"897a42f20db3ee955b1cc64506c040b0b1dcebe45d9ba3147e133d110f487f6e","signature":"3089238aed154b07430dd80de65df3115d268f21f1afcd8568a58d65c7827c5f"},{"version":"2d41bac312ef892971b2344a102feb99985e87f79edc18ed2c43ece97703fb91","signature":"2642375958909546f682d51f9c3682f553ae5f919f7b4a77d49262c200bca248"},{"version":"db3db9885deb334e6606785a0bfe7aecdcae172d36a6b4bd55958c756b92ac6c","signature":"79cdba32abf1fd279e588363d3048cb4b3d537a81530d32079cea1df22d66f93"},"1fcb8b15db812281d69a3090d488903f9e93033004aef9d8889ca3ad0753a96f","bdf5a95eb0a2dd1d39805bdf51b46ba012bb9b92b2ddaae16219595bba7678a5","9f794a0e8550a03baff865a3961cc22afbd85bc4ba9672bdda036971928f85f4","66a697d1e4cdbf25cdce4644a8085a8563041fa8c7731d4d9f5e8f22e66ba72c","a0c8e17f4d1ea2704c62d7349bc3b8d9a12e3761b5960cb44144d3f0333b3fcb","3471c0df3d0391e1dffe6e8bf150294531b2b71a2afa5f2b86e52bf84a5db60a","5d4df4de055eddf3187094f938a640f8d96e4c551a47d6686596fdb6ba4c3014","8bc2cad630da1033c1fd8d7df2bffb18af0da6113bd086a8bbec04a2471a1e00","a1059d1bbc8ad46bfe668b8450e7e8002887c4ab987bdb96d6108d8023f8bb8f","5134885e9648e2c6745f8aa1c3e7f5ab3b3617258b3d81ca02de6655ede3d74e","4f1ae3f24125216cf07c5211a3f00d2bb4782d7cc76c0681603f8249f9232ff0","d3fb92a5640f83f7844d60b35317a0f95c27e3658a749d76d218c461ad091668","d1f8bfcd91b284657ef8187c55ace7db91a3c43e642c3f14e54364154932f7e4","f54c92bfcae54f360fe79514746efce4870e4ddabc064e95d406bba291e9f672","175fd7186fa6a70f9db9b270a04a503cae23cf01cb77e3905bac115c38424cf7","c993f7ed1b8e1023c1f2ee5b262dbc3b70b27475674e40a53a58591f9972dacc","c914014ab7c7001178663f29d31a495398234a41219af61f26d7e8e91b46af96","277afd6ab6ec72889e2988e0ddd7d138c1f512e68a1fa4e90eedfd71e2097a51","c0908f85f2b645d375127a3b53a17a65f782e17962d5c1eb68f08b1188acbf15","3fadac5d409cc2f27b1d2f4e7568600f02840205f301c9ae7a3068b46476438b","da6aae64ad559286830fd44c81e3d33303348f184af7db4fde8dd99ae9749407","3633f87c97d359cb55fa7bf0668fb2be8a23342951af6ec2d06e6d0cf7409371","cc3a5427d44fc77ff25e80b3edee4650a51f83de761faf5e633994ecf1ab1b44","b350eda75c6e47299b36002b31d5b220c405c21c365e708989829db013fadbb4","f421882756b6714834ae4687ab1aeadf344a1cc45437d2edffbac020ff3801c1","1d61d6ad832dabafbf63b86c5a79d704f2c8763ada9318e135b17a3cb2d09b32","e5cef5de3e5ad3436d414d20743231e284733b9cf4375dc79eff4fcca4282f99","e624419ba84e33e661e89a28083119ca41f6953dba09a4f82b660684087afe6d","942be430bd0feaced2e3e598273b17e50ea565ec9dac840b580b0b99e1a3cd5c","73350006cec5a0c6b71d53b0b0ddbfb82be96752a9c4e3c904c59e633bc9485e","a7df5c2e9594966c7e0d4a763b13ed5727506d892669df5f7bc9826f539c1d35","258cc5cd6891f6bcbaccefd953997038844e7f65d582cac987ffabf7181bcd4c","00a6db28fc4df6ddf10adbe630d9df620ec13af19039c1869653e60dafa739d2","649324d5abb5464aabe35d86cd0eef16562df811f0971481cee664afa5acbc88",{"version":"628749b6edfc907c32583a77f7dde111642dbfc13265fa566e9a8fa47f224b51","signature":"495944b274165419ec08446dbd612d6276e2c12b92caa1f1e6c645cbc044ef25"},{"version":"e2f7d4348da1a42007547574ec71504de5e9df04d270bcc4c672bec1068257e4","signature":"0d7e153773886e59a74ffe1fac08bef805541411de160b9f3af36f8a6a3c6022"},{"version":"70fa251413c8e1926804d27e8aa01f96bf56141270e8adaeedfeaf0cc7147cef","signature":"2e85c128d27849ff4bd436f75d32d8a64d9013d420f09c82c6eae63cb7131020"},{"version":"334a6eff67fdb6feabbe5a612552a0714c424ccd07abbb096672085e7d43fb4a","signature":"19756a360a54eda2a10138b94b37a87519fd1a27c678a1b82187295e40bbfacd"},{"version":"722e48bdd1c494feabfb081d7d582d4554276abacce92f69128511918c125273","signature":"b195f1ad5886c1600c53bc7296210f9ded9a9a673e01988eecf9f20f48a4d9d5"},{"version":"1b5f109f8e1b74f648bf19b878188928678f443c2b2a21db0861f57d0715ef69","signature":"55310e6719d6bd9462e76cbba6a582712b30a85ee4949b8d98e14e0f46738e78"},{"version":"d184310a8c121c1ed754995dc55f8ca212bb1ef94979f99423dcdc48569b3c51","signature":"99ec28bacd04a3185d90660fe18bae48f33cbb1d50c73c64cae98e67f7c0ca01"},{"version":"48d475a0c6f91f62a89b128923cdec08f1f30a12df0068493f0d9b2774125b01","signature":"6a90b1b75bb0eb776ae223adc1f3f1cc343abf3e68df619933a3248910061290"},{"version":"e581d928f182594fe6aa7c0dd2e0ce02fe65fb53b7d40a59af9c2f171eee6428","signature":"1ac721bca31657133deb33e2ae005d557e8e6e0aa9a466142a2b0388e2e2638c"},{"version":"f2cf0410b95d14c070af93ed700294f19680b00a823d2eb5c8dd6ce433381e4b","signature":"85744b65d5c0962e4e7df8e5b1d1646a759e21fffd160b91d207b78d28da7724"},{"version":"bcc7e1fd0b70240f11846f0c5a284be69834446899b64477371cee7aaca38965","signature":"bab97a4f0736f1c1cd0546f79f993ecf30b34404cf4479a4f39068915880cb1c"},{"version":"6720778d4192df7ececcfd9dfebed8a006c9c44f88fe8b74880ab3ba7e14cce4","signature":"121c82998e23aa414d41a2f08e108074760318a1c11a2a5183b88b0d9be4ef60"},{"version":"e3fe28954899e21bf8a7db496cb4b90313e826bb5ae938d84bc73c3bdaa31cc9","signature":"4e1f22dbfc0754b698f1e291c7c92bf1220834bd5620207084236399cfd02e2d"},{"version":"7f2a2cdf8eecbe353d449055d91c6ee619f90ca3b3a49ba5a44563c44aab5d1a","signature":"8e6165fa13e0d2f40e2403ab20b72804d02c663709a3f7383a320050e893fe8b"},{"version":"a02cb9d0a7363cbbce45fa86bbd7d64615811e30f2a7c47a2718fcf53f20eae7","signature":"9af2721670eb3402e476cd827256d4af7ab1d6db57f1615cbef18c75164df9e5"},"14c94f7888c75007a94132f03caef0f6b58bcb136c2994213fd2d3b99f3d7f85","4695042a55a75a6c62dc57f2efe60ef3c7bbe19adedb5081f6e51dd664bbc3f7","b006ad8d854471e7a270bd8918508090961bdc1cfe77ed51f13f471fe682acac","310901df1081433ff7c3b7918496cabb92ded208b04294d3d2bd35acae2de836","c8646410cd2a6bf05eb7e7a51c881776410d07fd5d8f75092a2c815c9c6fda52",{"version":"127604bb56d364ecc35cbb4927ba7c53f552353fc7913b07a4f5cc957210aabd","signature":"973a1e0a155ab26d66226ff9d64a36cf61227e9240b21cabdc67df29847a6599"},{"version":"dcea5769c8b69d7b7a5ee6ffd4d22260e47d53d22990e91d504cbdc0c0120c14","signature":"16c51743932253da5b661b0a5068eb1423a6f020f62e6783ce8ac5259cff10f2"},{"version":"67be5e00299e02d108b294758dcc0218da9f2a2823dea61d708ddbe705771ae5","signature":"05fe3dec4dc02961a8959758da54c6ff9d32a232183041163d4d52cc6bf39015"},{"version":"e2e5ebf01c7004f157b8c750fdddb9f227fbf3119a87297e3a014db04c3f0887","signature":"fc6fe9c667e291d0bbdc904c921d2c1d385175f8c135d9e549298c96265acaec"},{"version":"6b0da45d7a1027dd4a9b14ac009b018761e8851c84a9e54ecc1be9086f0516c6","signature":"38fd30580198d072da98f6dbcb7535f47359ca91ffe57e3b9bfd1961a3b209ab"},{"version":"407e1457c37a63fc162e15d0684d0f196550e0db0c84903c6057a37359305d20","signature":"4d0ada1fd2655eab6195efa682371a7a4322868bc75c466832a2776c4a7ea4c1"},{"version":"4c408d170f00539f8957a9cfce1d7f3e4a2d36651dbf4b16337a7af5c568d7e5","signature":"a0c04e7f7ac63b60e113ff0a7ad4fbf9214babb1db0572641709a5859710e27c"},"4489c6a9fde8934733aa7df6f7911461ee6e9e4ad092736bd416f6b2cc20b2c6","2c8e55457aaf4902941dfdba4061935922e8ee6e120539c9801cd7b400fae050","8041cfce439ff29d339742389de04c136e3029d6b1817f07b2d7fcbfb7534990","670a76db379b27c8ff42f1ba927828a22862e2ab0b0908e38b671f0e912cc5ed","9d38964b57191567a14b396422c87488cecd48f405c642daa734159875ee81d9","069bebfee29864e3955378107e243508b163e77ab10de6a5ee03ae06939f0bb9",{"version":"64d4b35c5456adf258d2cf56c341e203a073253f229ef3208fc0d5020253b241","affectsGlobalScope":true},"ee7d8894904b465b072be0d2e4b45cf6b887cdba16a467645c4e200982ece7ea","f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","bc3cba7b0af2d52e7425299aee518db479d44004eff6fbbd206d1ee7e5ec3fb5","afe73051ff6a03a9565cbd8ebb0e956ee3df5e913ad5c1ded64218aabfa3dcb5","035a5df183489c2e22f3cf59fc1ed2b043d27f357eecc0eb8d8e840059d44245","a4809f4d92317535e6b22b01019437030077a76fec1d93b9881c9ed4738fcc54","5f53fa0bd22096d2a78533f94e02c899143b8f0f9891a46965294ee8b91a9434","0d14fa22c41fdc7277e6f71473b20ebc07f40f00e38875142335d5b63cdfc9d2","d8aab31ba8e618cc3eea10b0945de81cb93b7e8150a013a482332263b9305322","462bccdf75fcafc1ae8c30400c9425e1a4681db5d605d1a0edb4f990a54d8094","5923d8facbac6ecf7c84739a5c701a57af94a6f6648d6229a6c768cf28f0f8cb","7adecb2c3238794c378d336a8182d4c3dd2c4fa6fa1785e2797a3db550edea62","dc12dc0e5aa06f4e1a7692149b78f89116af823b9e1f1e4eae140cd3e0e674e6","1bfc6565b90c8771615cd8cfcf9b36efc0275e5e83ac7d9181307e96eb495161","8a8a96898906f065f296665e411f51010b51372fa260d5373bf9f64356703190","7f82ef88bdb67d9a850dd1c7cd2d690f33e0f0acd208e3c9eba086f3670d4f73",{"version":"ccfd8774cd9b929f63ff7dcf657977eb0652e3547f1fcac1b3a1dc5db22d4d58","affectsGlobalScope":true},"d92dc90fecd2552db74d8dc3c6fb4db9145b2aa0efe2c127236ba035969068d4","96d14f21b7652903852eef49379d04dbda28c16ed36468f8c9fa08f7c14c9538","8841e2aa774b89bd23302dede20663306dc1b9902431ac64b24be8b8d0e3f649","916be7d770b0ae0406be9486ac12eb9825f21514961dd050594c4b250617d5a8","254d9fb8c872d73d34594be8a200fd7311dbfa10a4116bfc465fba408052f2b3","d88a5e779faf033be3d52142a04fbe1cb96009868e3bbdd296b2bc6c59e06c0e","d8f7109e14f20eb735225a62fd3f8366da1a8349e90331cdad57f4b04caf6c5a","cf3d384d082b933d987c4e2fe7bfb8710adfd9dc8155190056ed6695a25a559e","9871b7ee672bc16c78833bdab3052615834b08375cb144e4d2cba74473f4a589","c863198dae89420f3c552b5a03da6ed6d0acfa3807a64772b895db624b0de707","8b03a5e327d7db67112ebbc93b4f744133eda2c1743dbb0a990c61a8007823ef","86c73f2ee1752bac8eeeece234fd05dfcf0637a4fbd8032e4f5f43102faa8eec","42fad1f540271e35ca37cecda12c4ce2eef27f0f5cf0f8dd761d723c744d3159","ff3743a5de32bee10906aff63d1de726f6a7fd6ee2da4b8229054dfa69de2c34","83acd370f7f84f203e71ebba33ba61b7f1291ca027d7f9a662c6307d74e4ac22","1445cec898f90bdd18b2949b9590b3c012f5b7e1804e6e329fb0fe053946d5ec","0e5318ec2275d8da858b541920d9306650ae6ac8012f0e872fe66eb50321a669","cf530297c3fb3a92ec9591dd4fa229d58b5981e45fe6702a0bd2bea53a5e59be","c1f6f7d08d42148ddfe164d36d7aba91f467dbcb3caa715966ff95f55048b3a4","f4e9bf9103191ef3b3612d3ec0044ca4044ca5be27711fe648ada06fad4bcc85","0c1ee27b8f6a00097c2d6d91a21ee4d096ab52c1e28350f6362542b55380059a","7677d5b0db9e020d3017720f853ba18f415219fb3a9597343b1b1012cfd699f7","bc1c6bc119c1784b1a2be6d9c47addec0d83ef0d52c8fbe1f14a51b4dfffc675","52cf2ce99c2a23de70225e252e9822a22b4e0adb82643ab0b710858810e00bf1","770625067bb27a20b9826255a8d47b6b5b0a2d3dfcbd21f89904c731f671ba77","d1ed6765f4d7906a05968fb5cd6d1db8afa14dbe512a4884e8ea5c0f5e142c80","799c0f1b07c092626cf1efd71d459997635911bb5f7fc1196efe449bba87e965","2a184e4462b9914a30b1b5c41cf80c6d3428f17b20d3afb711fff3f0644001fd","9eabde32a3aa5d80de34af2c2206cdc3ee094c6504a8d0c2d6d20c7c179503cc","397c8051b6cfcb48aa22656f0faca2553c5f56187262135162ee79d2b2f6c966","a8ead142e0c87dcd5dc130eba1f8eeed506b08952d905c47621dc2f583b1bff9","a02f10ea5f73130efca046429254a4e3c06b5475baecc8f7b99a0014731be8b3","c2576a4083232b0e2d9bd06875dd43d371dee2e090325a9eac0133fd5650c1cb","4c9a0564bb317349de6a24eb4efea8bb79898fa72ad63a1809165f5bd42970dd","f40ac11d8859092d20f953aae14ba967282c3bb056431a37fced1866ec7a2681","cc11e9e79d4746cc59e0e17473a59d6f104692fd0eeea1bdb2e206eabed83b03","b444a410d34fb5e98aa5ee2b381362044f4884652e8bc8a11c8fe14bbd85518e","c35808c1f5e16d2c571aa65067e3cb95afeff843b259ecfa2fc107a9519b5392","14d5dc055143e941c8743c6a21fa459f961cbc3deedf1bfe47b11587ca4b3ef5","a3ad4e1fc542751005267d50a6298e6765928c0c3a8dce1572f2ba6ca518661c","f237e7c97a3a89f4591afd49ecb3bd8d14f51a1c4adc8fcae3430febedff5eb6","3ffdfbec93b7aed71082af62b8c3e0cc71261cc68d796665faa1e91604fbae8f","662201f943ed45b1ad600d03a90dffe20841e725203ced8b708c91fcd7f9379a","c9ef74c64ed051ea5b958621e7fb853fe3b56e8787c1587aefc6ea988b3c7e79","2462ccfac5f3375794b861abaa81da380f1bbd9401de59ffa43119a0b644253d","34baf65cfee92f110d6653322e2120c2d368ee64b3c7981dff08ed105c4f19b0","7d8ddf0f021c53099e34ee831a06c394d50371816caa98684812f089b4c6b3d4","7d2a0ba1297be385a89b5515b88cd31b4a1eeef5236f710166dc1b36b1741e1b","9d92b037978bb9525bc4b673ebddd443277542e010c0aef019c03a170ccdaa73","ab82804a14454734010dcdcd43f564ff7b0389bee4c5692eec76ff5b30d4cf66","bae8d023ef6b23df7da26f51cea44321f95817c190342a36882e93b80d07a960","ae271d475b632ce7b03fea6d9cf6da72439e57a109672671cbc79f54e1386938"],"options":{"composite":true,"declaration":true,"declarationMap":true,"emitDeclarationOnly":true,"esModuleInterop":true,"inlineSources":true,"module":1,"outDir":"./types","rootDir":"../src","sourceMap":true,"strict":true,"target":7},"fileIdsList":[[666],[72,108,109,110,125],[109,110,126,127],[108,109],[108,125,128,131],[108,128,131,132],[129,130,131,133,134],[108,131],[108,125,128,129,130,133],[108,116],[108],[72,108],[60,108],[112,113,114,115,116,117,118,119,120,121,122,123,124],[108,114,115],[108,114,116],[605,609,610],[605,608],[608],[609,611,613],[605,608,609,610,611,612],[605,608,612,616,617,618],[605,608,612,619],[605],[605,606],[606,607],[605,608,614,617,619,620],[615],[616,618,622,625,626],[616,618,626],[108,608,612,616,617,619,622],[616,626],[616,619,623],[608,617,619],[616,619,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637],[616,624],[108,624],[605,612,616,617,618,619,620,623],[616,618,622,624],[616,623,624],[108,135,392,393],[393,394],[392],[108,387],[387,388,389,390,391],[108,359,366,367],[108,359,366,367,387],[108,359,366,367,371],[108,359,366,367,368,370,371],[108,359,366,367,369],[108,359,366,367,372,373,375,376],[365,387],[108,359,366,367,372],[108,359,366,367,370],[108,359,366,367,383],[108,359,366,367,384],[111,356,359,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386],[357],[357,358],[357,366,367,372,373],[359,365,366],[402,403],[72,108,392,395,401],[395,402],[216],[545,546,547],[216,544,545],[249,258,259,262],[249,258,261],[250,253,254,256],[250,251,252],[253,254,256,257],[250,251,255],[261,267],[249,258,261,267],[258,261,267],[258,261,263,264,265,266],[249,258,259,260,261,262,267],[249,258,260,262],[249,258],[250],[144,167],[144],[189,190,191,192,194,195,196],[167,189,190,191,192,194,195],[144,167,193],[198],[201],[144,193],[202,203,204],[197],[193,197,199,200,205,206,213,215,235,236,354],[167,200,205],[208],[207,209,210,211,212],[144,167,193,197],[167,197,214],[167,214,215,234],[167,206,353],[138,144],[654,655,656,657],[568],[548,567],[560,561,562,563,564,565,566],[560],[562],[560,562],[425],[108,228,424],[108,228,425],[108,228,396],[396],[396,397,398,399,400],[108,228],[228,427],[427,428,429,430,431,432,433,434,435,436],[228,427,428],[61,108,228,427,428],[105,108,228,427,428],[228,428],[167,216,223,224],[225],[229],[224,225,226,229,230,231,232,233],[108,226,228,231],[108,167,225,228,229],[224,231],[108,167,216,223,225,228],[167,223],[167,237],[237,238],[237,238,239,240],[167],[188,353,475,492,493,506,531],[529],[167,504,519,527,528,530],[518],[188,353,455,517],[108,223,228,426,437,492,493,494,506],[167,188,492,506],[437,495],[497],[494,495,496,498,501,503],[500],[495,499,504],[437,495,496],[167,437],[502],[495,496],[509,524,525,526],[492,506],[505,506,507,508],[492,506,507],[167,492,505,506],[167,492,506],[522,523],[167,188,485,522],[167,353,485],[167,184,188,353,462,475,485,492,493,504,506,509,511,519,521,524],[520],[167,353,475,492,493,506,527],[144,167,484],[108,167,242],[167,350],[319],[167,242,319,347,350,351,352],[108,167,241,242],[243,244,245,246,348,349],[138,144,347],[138,144,245],[277],[277,283],[277,282,284,285],[277,282,286],[282,283,284,285,286,287],[289,290],[278,279,280,281,288,291,292,293,294,295,296,297,298],[277,291],[277,278,293,295,296],[277,291,294],[277,299,300,301,302],[144,277,299,350],[334],[347],[337,338,339,340,341,342,343,344,345],[167,269],[319,343,350],[269,347,350],[144,320],[269,270,320,323,333,334,335,346],[144,167,303,319],[347,350],[268,270],[270],[350],[320],[167,323],[247,248,271,272,273,274,275,276,321,322,324,325,326,327,328,329,330,331,332],[167,325],[247,248,271,272,273,274,275,276,321,322,324,325,326,327,328,329,330,331,350],[167,268,269],[234,333],[167,270],[317],[144,304],[305,306,307,308,309,310,311,312,313,314,315,316],[304,317,318],[303],[353],[441],[440],[144,167,447],[268],[167,241,353],[144,353,454,455],[438,439,441,442,443,444,445,448,449,450,451,452,453,454,456,457,458,476,477,479,480,481,482,483,486,487,488,489,490,491],[144,167,475],[144,167,353,441,479],[158],[478],[144,167,268,353,477],[144,353,477],[144,353,475,478,480,485,486],[144,167,441,444,456,479,480],[353,455],[486],[536],[536,537,538],[147],[144,147],[145,146,147,148,149,150,151,152,153,154,155,156,159,160,161,162,163,164,165,166],[138,144,145],[135,147,153,155],[147,148],[144,162],[108,362],[360,361,364],[360,363],[108,360],[412,413],[666,667,668,669,670],[666,668],[157],[672,673,674],[73,108],[677],[678],[689],[683,688],[579,581,582,583,584,585,586,587,588,589,590,591],[579,580,582,583,584,585,586,587,588,589,590,591],[580,581,582,583,584,585,586,587,588,589,590,591],[579,580,581,583,584,585,586,587,588,589,590,591],[579,580,581,582,584,585,586,587,588,589,590,591],[579,580,581,582,583,585,586,587,588,589,590,591],[579,580,581,582,583,584,586,587,588,589,590,591],[579,580,581,582,583,584,585,587,588,589,590,591],[579,580,581,582,583,584,585,586,588,589,590,591],[579,580,581,582,583,584,585,586,587,589,590,591],[579,580,581,582,583,584,585,586,587,588,590,591],[579,580,581,582,583,584,585,586,587,588,589,591],[579,580,581,582,583,584,585,586,587,588,589,590],[56],[59],[60,65,92],[61,72,73,80,89,100],[61,62,72,80],[63,101],[64,65,73,81],[65,89,97],[66,68,72,80],[67],[68,69],[72],[71,72],[59,72],[72,73,74,89,100],[72,73,74,89],[72,75,80,89,100],[72,73,75,76,80,89,97,100],[75,77,89,97,100],[56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107],[72,78],[79,100,105],[68,72,80,89],[81],[82],[59,83],[84,99,105],[85],[86],[72,87],[87,88,101,103],[60,72,89,90,91],[60,89,91],[89,90],[92],[93],[72,95,96],[95,96],[65,80,89,97],[98],[80,99],[60,75,86,100],[65,101],[89,102],[103],[104],[60,65,72,74,83,89,100,103,105],[89,106],[108,227],[697,736],[697,721,736],[736],[697],[697,722,736],[697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735],[722,736],[737],[740],[510],[570,571,572,573,574,575,576],[570],[572],[570,572],[446],[593,594,595],[593],[594],[179],[179,180,181,182,183],[168,169,170,171,172,173,174,175,176,177,178],[681,684],[681,684,685,686],[683],[680,687],[682],[137,139,140,141,142,143],[137,138],[139],[138,139],[137,139],[167,188,355,423,531],[532,534],[423,533],[167,188,241],[460,461],[167,184,185,186],[185],[136,185,186,187],[186],[407],[407,408,411,415],[414],[167,409,410],[541,542,543],[223,541],[167,223,541],[167,216,223],[167,188,553,557],[558],[167,217],[217,218,219,220,221,222],[167,216],[422],[135,167,184,188,355,404,405,421],[72,108,167,188],[406],[406,417,418,419,420],[406,416],[549],[540,549,551,552],[167,188,409,416,539,540,549,550],[167,416,544,548],[167,467,468,469],[241,467,468,470],[465,466,467,468,469,470,474],[167,223,467,469,475],[167,188,416,459,465,467,470],[167,184,188,241,416,459,462,463,464,465,466,468,469,470],[167,223,466,467,468],[471,472,473],[167,223,416,466,468,469],[167,223,466,468,469],[167,188,467],[167,223,468,470],[516],[188,416,512,514,515],[513,514],[515,516],[167,188,553,554],[554,555,556],[108,167,188,553,554],[167,553],[167,597],[167,559,592,597,602],[167,409,410,416,592,597,603],[167,597,599,639],[128,135,167,591,592,597,621,638],[167,416,597],[167,410,416,533,577,592,597,599,643],[72,167,409,553,559,592,597,598,645],[72,167,535,553,577,592,597],[167,409,553,569,577,592,644,647,648],[72,409,416,553,591,592,597],[597,598,600,643,662,664],[72,125,128,135,167,188,241,409,416,462,533,535,553,559,569,577,578,591,592,597,598,600,601,602,603,604,640,641,642,644,645,646,647,648,649,650,651,652,653,661,662,663],[135,167,409,553,559,596],[167,416,592,599],[241,597],[167,409,416,559,592,597,598,601],[416,559,597],[167,409,416,592,597,599],[591,596,597],[167,553,592,597],[416,569,592,597],[167,416,592,659],[52,167,416,592,597,599,614,659,660],[409,416,591,592,597,599,600,664],[52,409,416,597,614],[167,416,597,664],[52,241,416,597,600,614],[597],[597,639],[72,167,553,559,597],[72,167,535,553,597],[167,409,553,569,644,647,648],[72,409,553,597],[158,167],[128,135,167,188,462,535,553,559,569,597,647],[167,409,559,597],[559,597],[158,167,409,597],[167,553,597],[569,597],[167,597,614,660],[409,597,664],[409,597],[597,664]],"referencedMap":[[668,1],[126,2],[128,3],[110,4],[132,5],[133,6],[129,6],[135,7],[130,6],[134,8],[131,9],[117,10],[114,11],[121,12],[115,10],[112,13],[125,14],[119,11],[116,15],[118,16],[611,17],[610,18],[609,19],[614,20],[613,21],[619,22],[620,23],[606,24],[607,25],[608,26],[621,27],[616,28],[627,29],[628,30],[623,31],[629,32],[630,33],[631,33],[622,34],[638,35],[633,29],[632,36],[634,37],[624,38],[635,32],[636,30],[626,39],[637,36],[625,40],[617,18],[394,41],[395,42],[393,43],[390,44],[389,44],[388,44],[392,45],[374,46],[379,47],[368,46],[373,48],[372,49],[370,50],[377,51],[378,46],[380,52],[381,53],[383,54],[384,55],[385,56],[387,57],[358,58],[359,59],[375,60],[367,61],[404,62],[402,63],[403,64],[545,65],[548,66],[546,67],[547,67],[260,68],[262,69],[257,70],[253,71],[254,71],[258,72],[256,73],[263,74],[264,75],[265,76],[267,77],[266,74],[268,78],[261,79],[259,80],[252,81],[255,71],[189,82],[190,83],[191,83],[192,82],[197,84],[196,85],[194,86],[195,82],[199,87],[198,82],[202,88],[201,89],[205,90],[203,82],[204,91],[355,92],[207,86],[208,93],[209,94],[210,86],[213,95],[212,96],[214,86],[215,97],[235,98],[236,97],[354,99],[193,100],[658,101],[569,102],[568,103],[567,104],[561,105],[563,106],[565,107],[564,107],[426,108],[425,109],[424,110],[397,111],[398,112],[401,113],[399,112],[396,65],[400,114],[428,115],[437,116],[433,117],[432,118],[435,117],[434,119],[436,120],[431,120],[430,117],[429,120],[225,121],[226,122],[230,123],[234,124],[232,125],[231,126],[233,127],[229,128],[224,129],[238,130],[239,131],[241,132],[237,133],[216,12],[529,134],[530,135],[531,136],[519,137],[518,138],[495,139],[494,140],[497,141],[498,142],[504,143],[501,144],[500,145],[499,146],[496,147],[503,148],[502,149],[527,150],[507,151],[509,152],[508,153],[506,154],[505,155],[524,156],[523,157],[522,158],[526,151],[525,159],[520,133],[521,160],[528,161],[485,162],[484,82],[351,163],[242,164],[352,165],[353,166],[243,167],[244,133],[245,133],[350,168],[348,169],[246,170],[277,133],[278,171],[279,171],[280,171],[281,171],[282,171],[284,172],[286,173],[287,174],[288,175],[285,171],[283,171],[289,171],[291,176],[290,171],[292,171],[293,171],[299,177],[294,178],[297,179],[298,171],[295,180],[296,171],[303,181],[301,171],[300,171],[302,182],[335,183],[337,133],[338,184],[346,185],[339,133],[341,186],[342,133],[344,187],[343,188],[345,189],[347,190],[320,191],[247,184],[248,192],[271,193],[272,194],[273,193],[275,133],[276,195],[321,196],[324,197],[333,198],[326,199],[325,133],[327,133],[328,164],[332,200],[329,195],[330,197],[331,184],[270,201],[334,202],[323,203],[318,204],[305,205],[314,205],[306,205],[307,205],[316,205],[308,205],[309,205],[317,206],[315,205],[310,205],[313,205],[311,205],[312,205],[319,207],[304,83],[455,208],[439,209],[442,210],[443,211],[445,210],[448,212],[451,213],[453,214],[456,215],[492,216],[476,217],[458,133],[480,218],[481,219],[479,220],[478,221],[482,222],[487,223],[477,100],[486,224],[489,225],[490,226],[491,133],[441,211],[537,227],[538,227],[539,228],[145,83],[146,83],[148,229],[149,83],[150,83],[151,230],[147,83],[167,231],[155,232],[156,233],[159,219],[165,234],[166,235],[363,236],[362,11],[365,237],[360,11],[364,238],[361,239],[414,240],[671,241],[667,1],[669,242],[670,1],[410,11],[158,243],[675,244],[676,245],[678,246],[679,247],[690,248],[689,249],[580,250],[581,251],[579,252],[582,253],[583,254],[584,255],[585,256],[586,257],[587,258],[588,259],[589,260],[590,261],[591,262],[56,263],[57,263],[59,264],[60,265],[61,266],[62,267],[63,268],[64,269],[65,270],[66,271],[67,272],[68,273],[69,273],[70,274],[71,275],[72,276],[73,277],[74,278],[75,279],[76,280],[77,281],[108,282],[78,283],[79,284],[80,285],[81,286],[82,287],[83,288],[84,289],[85,290],[86,291],[87,292],[88,293],[89,294],[91,295],[90,296],[92,297],[93,298],[95,299],[96,300],[97,301],[98,302],[99,303],[100,304],[101,305],[102,306],[103,307],[104,308],[105,309],[106,310],[694,11],[228,311],[696,11],[721,312],[722,313],[697,314],[700,314],[719,312],[720,312],[710,312],[709,315],[707,312],[702,312],[715,312],[713,312],[717,312],[701,312],[714,312],[718,312],[703,312],[704,312],[716,312],[698,312],[705,312],[706,312],[708,312],[712,312],[723,316],[711,312],[699,312],[736,317],[730,316],[732,318],[731,316],[724,316],[725,316],[727,316],[729,316],[733,318],[734,318],[726,318],[728,318],[738,319],[741,320],[511,321],[577,322],[571,323],[573,324],[575,325],[574,325],[447,326],[596,327],[594,328],[595,329],[175,330],[177,330],[176,330],[174,330],[184,331],[179,332],[170,330],[171,330],[172,330],[173,330],[685,333],[687,334],[686,333],[684,335],[688,336],[683,337],[144,338],[139,339],[140,340],[141,340],[142,341],[143,341],[138,342],[532,343],[535,344],[534,345],[460,346],[462,347],[187,348],[186,349],[188,350],[185,351],[408,352],[416,353],[415,354],[411,355],[544,356],[542,357],[543,358],[541,359],[558,360],[559,361],[218,362],[219,362],[221,362],[223,363],[217,364],[222,362],[423,365],[422,366],[406,367],[420,368],[419,368],[421,369],[417,370],[418,368],[550,371],[552,371],[553,372],[551,373],[549,374],[470,375],[469,376],[475,377],[464,378],[468,379],[467,380],[471,381],[474,382],[472,383],[473,384],[465,385],[466,386],[517,387],[516,388],[515,389],[514,390],[555,391],[557,392],[556,393],[554,394],[659,395],[603,396],[604,397],[640,398],[639,399],[641,398],[642,400],[644,401],[646,402],[647,403],[649,404],[648,405],[665,406],[592,133],[664,407],[597,408],[643,409],[650,410],[602,411],[598,412],[651,413],[652,414],[645,415],[653,416],[660,417],[661,418],[601,419],[662,420],[600,421],[663,422]],"exportedModulesMap":[[668,1],[126,2],[128,3],[110,4],[132,5],[133,6],[129,6],[135,7],[130,6],[134,8],[131,9],[117,10],[114,11],[121,12],[115,10],[112,13],[125,14],[119,11],[116,15],[118,16],[611,17],[610,18],[609,19],[614,20],[613,21],[619,22],[620,23],[606,24],[607,25],[608,26],[621,27],[616,28],[627,29],[628,30],[623,31],[629,32],[630,33],[631,33],[622,34],[638,35],[633,29],[632,36],[634,37],[624,38],[635,32],[636,30],[626,39],[637,36],[625,40],[617,18],[394,41],[395,42],[393,43],[390,44],[389,44],[388,44],[392,45],[374,46],[379,47],[368,46],[373,48],[372,49],[370,50],[377,51],[378,46],[380,52],[381,53],[383,54],[384,55],[385,56],[387,57],[358,58],[359,59],[375,60],[367,61],[404,62],[402,63],[403,64],[545,65],[548,66],[546,67],[547,67],[260,68],[262,69],[257,70],[253,71],[254,71],[258,72],[256,73],[263,74],[264,75],[265,76],[267,77],[266,74],[268,78],[261,79],[259,80],[252,81],[255,71],[189,82],[190,83],[191,83],[192,82],[197,84],[196,85],[194,86],[195,82],[199,87],[198,82],[202,88],[201,89],[205,90],[203,82],[204,91],[355,92],[207,86],[208,93],[209,94],[210,86],[213,95],[212,96],[214,86],[215,97],[235,98],[236,97],[354,99],[193,100],[658,101],[569,102],[568,103],[567,104],[561,105],[563,106],[565,107],[564,107],[426,108],[425,109],[424,110],[397,111],[398,112],[401,113],[399,112],[396,65],[400,114],[428,115],[437,116],[433,117],[432,118],[435,117],[434,119],[436,120],[431,120],[430,117],[429,120],[225,121],[226,122],[230,123],[234,124],[232,125],[231,126],[233,127],[229,128],[224,129],[238,130],[239,131],[241,132],[237,133],[216,12],[529,134],[530,135],[531,136],[519,137],[518,138],[495,139],[494,140],[497,141],[498,142],[504,143],[501,144],[500,145],[499,146],[496,147],[503,148],[502,149],[527,150],[507,151],[509,152],[508,153],[506,154],[505,155],[524,156],[523,157],[522,158],[526,151],[525,159],[520,133],[521,160],[528,161],[485,162],[484,82],[351,163],[242,164],[352,165],[353,166],[243,167],[244,133],[245,133],[350,168],[348,169],[246,170],[277,133],[278,171],[279,171],[280,171],[281,171],[282,171],[284,172],[286,173],[287,174],[288,175],[285,171],[283,171],[289,171],[291,176],[290,171],[292,171],[293,171],[299,177],[294,178],[297,179],[298,171],[295,180],[296,171],[303,181],[301,171],[300,171],[302,182],[335,183],[337,133],[338,184],[346,185],[339,133],[341,186],[342,133],[344,187],[343,188],[345,189],[347,190],[320,191],[247,184],[248,192],[271,193],[272,194],[273,193],[275,133],[276,195],[321,196],[324,197],[333,198],[326,199],[325,133],[327,133],[328,164],[332,200],[329,195],[330,197],[331,184],[270,201],[334,202],[323,203],[318,204],[305,205],[314,205],[306,205],[307,205],[316,205],[308,205],[309,205],[317,206],[315,205],[310,205],[313,205],[311,205],[312,205],[319,207],[304,83],[455,208],[439,209],[442,210],[443,211],[445,210],[448,212],[451,213],[453,214],[456,215],[492,216],[476,217],[458,133],[480,218],[481,219],[479,220],[478,221],[482,222],[487,223],[477,100],[486,224],[489,225],[490,226],[491,133],[441,211],[537,227],[538,227],[539,228],[145,83],[146,83],[148,229],[149,83],[150,83],[151,230],[147,83],[167,231],[155,232],[156,233],[159,219],[165,234],[166,235],[363,236],[362,11],[365,237],[360,11],[364,238],[361,239],[414,240],[671,241],[667,1],[669,242],[670,1],[410,11],[158,243],[675,244],[676,245],[678,246],[679,247],[690,248],[689,249],[580,250],[581,251],[579,252],[582,253],[583,254],[584,255],[585,256],[586,257],[587,258],[588,259],[589,260],[590,261],[591,262],[56,263],[57,263],[59,264],[60,265],[61,266],[62,267],[63,268],[64,269],[65,270],[66,271],[67,272],[68,273],[69,273],[70,274],[71,275],[72,276],[73,277],[74,278],[75,279],[76,280],[77,281],[108,282],[78,283],[79,284],[80,285],[81,286],[82,287],[83,288],[84,289],[85,290],[86,291],[87,292],[88,293],[89,294],[91,295],[90,296],[92,297],[93,298],[95,299],[96,300],[97,301],[98,302],[99,303],[100,304],[101,305],[102,306],[103,307],[104,308],[105,309],[106,310],[694,11],[228,311],[696,11],[721,312],[722,313],[697,314],[700,314],[719,312],[720,312],[710,312],[709,315],[707,312],[702,312],[715,312],[713,312],[717,312],[701,312],[714,312],[718,312],[703,312],[704,312],[716,312],[698,312],[705,312],[706,312],[708,312],[712,312],[723,316],[711,312],[699,312],[736,317],[730,316],[732,318],[731,316],[724,316],[725,316],[727,316],[729,316],[733,318],[734,318],[726,318],[728,318],[738,319],[741,320],[511,321],[577,322],[571,323],[573,324],[575,325],[574,325],[447,326],[596,327],[594,328],[595,329],[175,330],[177,330],[176,330],[174,330],[184,331],[179,332],[170,330],[171,330],[172,330],[173,330],[685,333],[687,334],[686,333],[684,335],[688,336],[683,337],[144,338],[139,339],[140,340],[141,340],[142,341],[143,341],[138,342],[532,343],[535,344],[534,345],[460,346],[462,347],[187,348],[186,349],[188,350],[185,351],[408,352],[416,353],[415,354],[411,355],[544,356],[542,357],[543,358],[541,359],[558,360],[559,361],[218,362],[219,362],[221,362],[223,363],[217,364],[222,362],[423,365],[422,366],[406,367],[420,368],[419,368],[421,369],[417,370],[418,368],[550,371],[552,371],[553,372],[551,373],[549,374],[470,375],[469,376],[475,377],[464,378],[468,379],[467,380],[471,381],[474,382],[472,383],[473,384],[465,385],[466,386],[517,387],[516,388],[515,389],[514,390],[555,391],[557,392],[556,393],[554,394],[659,133],[603,423],[604,423],[640,424],[639,395],[641,424],[642,423],[644,395],[646,425],[647,426],[649,427],[648,428],[665,406],[592,429],[664,430],[597,408],[643,133],[650,423],[602,431],[598,432],[651,433],[652,423],[645,434],[653,435],[660,133],[661,436],[601,437],[662,438],[600,439],[663,423]],"semanticDiagnosticsPerFile":[668,666,126,109,128,110,127,132,133,129,135,130,134,131,117,114,121,115,112,120,125,122,123,124,119,116,113,118,611,610,609,614,613,619,620,606,607,608,605,621,616,615,612,627,628,623,629,630,631,622,638,633,632,634,624,635,636,626,637,625,617,618,394,395,393,390,389,388,392,391,374,379,368,373,372,370,377,378,380,382,381,383,384,385,387,358,357,359,375,356,369,367,366,376,371,386,404,402,403,405,545,548,546,547,409,260,262,249,257,253,254,258,256,263,264,265,267,266,268,261,259,252,250,251,255,189,190,191,192,197,196,194,195,199,198,200,202,201,205,203,204,206,355,207,208,209,210,213,211,212,214,215,235,236,354,193,656,654,655,657,658,569,568,566,567,561,560,563,562,565,564,426,425,424,397,398,401,399,396,400,428,437,433,432,435,434,436,427,431,430,429,225,226,230,234,232,231,233,229,224,238,240,239,241,237,216,529,530,531,519,518,495,494,497,498,504,501,500,499,496,503,502,527,507,509,508,506,505,524,523,522,526,525,493,520,521,528,485,484,351,242,352,353,243,244,245,350,348,246,349,277,278,279,280,281,282,284,286,287,288,285,283,289,291,290,292,293,299,294,297,298,295,296,303,301,300,302,269,335,337,338,346,339,340,341,342,344,343,345,336,347,320,247,248,271,272,273,274,275,276,321,322,324,333,326,325,327,328,332,329,330,331,270,334,323,318,305,314,306,307,316,308,309,317,315,310,313,311,312,319,304,455,438,439,442,443,444,445,448,449,450,451,452,453,454,456,457,492,476,458,480,481,479,478,482,483,487,488,477,486,489,490,491,441,440,537,538,539,536,145,146,148,149,150,151,152,153,154,147,167,155,156,159,160,161,162,163,164,165,166,363,362,365,360,364,361,412,414,413,671,667,669,670,410,158,463,672,675,673,676,677,678,679,690,689,674,691,580,581,579,582,583,584,585,586,587,588,589,590,591,692,157,56,57,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,58,107,75,76,77,108,78,79,80,81,82,83,84,85,86,87,88,89,91,90,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,693,694,695,512,228,227,696,721,722,697,700,719,720,710,709,707,702,715,713,717,701,714,718,703,704,716,698,705,706,708,712,723,711,699,736,735,730,732,731,724,725,727,729,733,734,726,728,738,737,739,533,740,741,511,510,576,577,571,570,573,572,575,574,111,680,446,447,578,596,594,595,593,513,178,175,177,176,174,184,179,183,180,182,181,170,171,172,168,169,173,681,685,687,686,684,688,459,683,682,137,144,139,140,141,142,143,138,8,10,9,2,11,12,13,14,15,16,17,18,3,4,22,19,20,21,23,24,25,5,26,27,28,29,6,33,30,31,32,34,7,35,40,41,36,37,38,39,1,42,532,535,534,460,461,462,136,187,186,188,185,408,416,415,407,411,544,542,543,541,558,559,218,219,220,221,223,217,222,423,422,406,420,419,421,417,418,540,550,552,553,551,549,470,469,475,464,468,467,471,474,472,473,465,466,517,516,515,514,555,557,556,554,599,659,603,604,640,639,641,642,644,646,647,649,648,665,592,664,597,643,650,602,598,651,652,645,653,660,661,601,662,600,663,47,48,49,50,51,52,43,53,54,55,44,45,46],"latestChangedDtsFile":"./types/index.d.ts"},"version":"4.9.5"}
+\ No newline at end of file
+diff --git a/dist/types/TransactionController.d.ts b/dist/types/TransactionController.d.ts
+index f4c0fa6672b24d7756513bd46c565f9da0ffd61a..37793f450f9e52815dcebc2557ec910ad6ab6021 100644
+--- a/dist/types/TransactionController.d.ts
++++ b/dist/types/TransactionController.d.ts
+@@ -115,7 +115,6 @@ export type PendingTransactionOptions = {
+ * @property transactionHistoryLimit - Transaction history limit.
+ * @property hooks - The controller hooks.
+ * @property hooks.afterSign - Additional logic to execute after signing a transaction. Return false to not change the status to signed.
+- * @property hooks.beforeApproveOnInit - Additional logic to execute before starting an approval flow for a transaction during initialization. Return false to skip the transaction.
+ * @property hooks.beforeCheckPendingTransaction - Additional logic to execute before checking pending transactions. Return false to prevent the broadcast of the transaction.
+ * @property hooks.beforePublish - Additional logic to execute before publishing a transaction. Return false to prevent the broadcast of the transaction.
+ * @property hooks.getAdditionalSignArguments - Returns additional arguments required to sign a transaction.
+@@ -148,7 +147,6 @@ export type TransactionControllerOptions = {
+ transactionHistoryLimit: number;
+ hooks: {
+ afterSign?: (transactionMeta: TransactionMeta, signedTx: TypedTransaction) => boolean;
+- beforeApproveOnInit?: (transactionMeta: TransactionMeta) => boolean;
+ beforeCheckPendingTransaction?: (transactionMeta: TransactionMeta) => boolean;
+ beforePublish?: (transactionMeta: TransactionMeta) => boolean;
+ getAdditionalSignArguments?: (transactionMeta: TransactionMeta) => (TransactionMeta | undefined)[];
+@@ -365,7 +363,6 @@ export declare class TransactionController extends BaseController Promise;
++ constructor({ blockTracker, getChainId, getEthQuery, getTransactions, isResubmitEnabled, getGlobalLock, publishTransaction, hooks, }: {
+ blockTracker: BlockTracker;
+ getChainId: () => string;
+ getEthQuery: (networkClientId?: NetworkClientId) => EthQuery;
+diff --git a/dist/types/helpers/PendingTransactionTracker.d.ts.map b/dist/types/helpers/PendingTransactionTracker.d.ts.map
+index 14d6402240dc02077ae66e3d049b03f529bbde30..bdca97bd140595aa27e63cd7dcb89389c7170341 100644
+--- a/dist/types/helpers/PendingTransactionTracker.d.ts.map
++++ b/dist/types/helpers/PendingTransactionTracker.d.ts.map
+@@ -1 +1 @@
+-{"version":3,"file":"PendingTransactionTracker.d.ts","sourceRoot":"","sources":["../../../src/helpers/PendingTransactionTracker.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAChD,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EAChB,MAAM,8BAA8B,CAAC;AACtC,OAAO,YAAY,MAAM,QAAQ,CAAC;AAIlC,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,UAAU,CAAC;AA6BpE,KAAK,MAAM,GAAG;IACZ,uBAAuB,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACnD,qBAAqB,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACjD,oBAAoB,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC9D,qBAAqB,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;CAChE,CAAC;AAKF,MAAM,WAAW,qCAAsC,SAAQ,YAAY;IAGzE,EAAE,CAAC,CAAC,SAAS,MAAM,MAAM,EACvB,SAAS,EAAE,CAAC,EACZ,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,GACrC,IAAI,CAAC;IAIR,IAAI,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;CACzE;AAED,qBAAa,yBAAyB;;IACpC,GAAG,EAAE,qCAAqC,CAAC;gBA8B/B,EACV,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,KAAK,GACN,EAAE;QACD,kBAAkB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7D,YAAY,EAAE,YAAY,CAAC;QAC3B,UAAU,EAAE,MAAM,MAAM,CAAC;QACzB,WAAW,EAAE,CAAC,eAAe,CAAC,EAAE,eAAe,KAAK,QAAQ,CAAC;QAC7D,eAAe,EAAE,MAAM,eAAe,EAAE,CAAC;QACzC,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC;QAClC,aAAa,EAAE,MAAM,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QACzC,kBAAkB,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3E,KAAK,CAAC,EAAE;YACN,6BAA6B,CAAC,EAAE,CAC9B,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC;YACb,aAAa,CAAC,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,OAAO,CAAC;SAC/D,CAAC;KACH;IAmBD,0BAA0B,aAQxB;IAEF;;;;OAIG;IACG,qBAAqB,CAAC,MAAM,EAAE,eAAe;IAwBnD,IAAI;CAqXL"}
+\ No newline at end of file
++{"version":3,"file":"PendingTransactionTracker.d.ts","sourceRoot":"","sources":["../../../src/helpers/PendingTransactionTracker.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,QAAQ,MAAM,qBAAqB,CAAC;AAChD,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EAChB,MAAM,8BAA8B,CAAC;AACtC,OAAO,YAAY,MAAM,QAAQ,CAAC;AAIlC,OAAO,KAAK,EAAE,eAAe,EAAsB,MAAM,UAAU,CAAC;AA6BpE,KAAK,MAAM,GAAG;IACZ,uBAAuB,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACnD,qBAAqB,EAAE,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACjD,oBAAoB,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAC9D,qBAAqB,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;CAChE,CAAC;AAKF,MAAM,WAAW,qCAAsC,SAAQ,YAAY;IAGzE,EAAE,CAAC,CAAC,SAAS,MAAM,MAAM,EACvB,SAAS,EAAE,CAAC,EACZ,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,GACrC,IAAI,CAAC;IAIR,IAAI,CAAC,CAAC,SAAS,MAAM,MAAM,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;CACzE;AAED,qBAAa,yBAAyB;;IACpC,GAAG,EAAE,qCAAqC,CAAC;gBA4B/B,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,KAAK,GACN,EAAE;QACD,YAAY,EAAE,YAAY,CAAC;QAC3B,UAAU,EAAE,MAAM,MAAM,CAAC;QACzB,WAAW,EAAE,CAAC,eAAe,CAAC,EAAE,eAAe,KAAK,QAAQ,CAAC;QAC7D,eAAe,EAAE,MAAM,eAAe,EAAE,CAAC;QACzC,iBAAiB,CAAC,EAAE,MAAM,OAAO,CAAC;QAClC,aAAa,EAAE,MAAM,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QACzC,kBAAkB,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3E,KAAK,CAAC,EAAE;YACN,6BAA6B,CAAC,EAAE,CAC9B,eAAe,EAAE,eAAe,KAC7B,OAAO,CAAC;YACb,aAAa,CAAC,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,OAAO,CAAC;SAC/D,CAAC;KACH;IAkBD,0BAA0B,aAQxB;IAEF;;;;OAIG;IACG,qBAAqB,CAAC,MAAM,EAAE,eAAe;IAwBnD,IAAI;CAiXL"}
+\ No newline at end of file
diff --git a/app/scripts/background.js b/app/scripts/background.js
index b1b19d6c2875..b369cd18ed0b 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -972,8 +972,6 @@ export function setupController(
updateBadge,
);
- controller.txController.initApprovals();
-
/**
* Formats a count for display as a badge label.
*
diff --git a/app/scripts/lib/transaction/mmi-hooks.test.ts b/app/scripts/lib/transaction/mmi-hooks.test.ts
index fee5dff83de5..45d0b83c2341 100644
--- a/app/scripts/lib/transaction/mmi-hooks.test.ts
+++ b/app/scripts/lib/transaction/mmi-hooks.test.ts
@@ -2,7 +2,6 @@ import { TransactionStatus } from '@metamask/transaction-controller';
import {
afterTransactionSign,
beforeCheckPendingTransaction,
- beforeTransactionApproveOnInit,
beforeTransactionPublish,
getAdditionalSignArguments,
} from './mmi-hooks';
@@ -85,24 +84,6 @@ describe('MMI hooks', () => {
});
});
- describe('beforeTransactionApproveOnInit', () => {
- it('returns true if txMeta has custodyStatus', () => {
- // TODO: Replace `any` with type
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const txMeta = { custodyStatus: TransactionStatus.approved } as any;
- const result = beforeTransactionApproveOnInit(txMeta);
- expect(result).toBe(false);
- });
-
- it('returns false if txMeta has no custodyStatus', () => {
- // TODO: Replace `any` with type
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const txMeta = { to: toMocked } as any;
- const result = beforeTransactionApproveOnInit(txMeta);
- expect(result).toBe(true);
- });
- });
-
describe('beforeCheckPendingTransaction', () => {
it('returns true if txMeta has custodyStatus', () => {
const txMeta = {
diff --git a/app/scripts/lib/transaction/mmi-hooks.ts b/app/scripts/lib/transaction/mmi-hooks.ts
index d4dc3cc4dcda..1716fe738c04 100644
--- a/app/scripts/lib/transaction/mmi-hooks.ts
+++ b/app/scripts/lib/transaction/mmi-hooks.ts
@@ -53,18 +53,6 @@ export function getAdditionalSignArguments(
return [txMeta.custodyStatus ? txMeta : undefined];
}
-/**
- * Whether or not should run the logic before approve the transaction when transaction controller is rebooted.
- *
- * @param txMeta - The transaction meta.
- */
-
-export function beforeTransactionApproveOnInit(
- txMeta: TransactionMeta,
-): boolean {
- return !txMeta?.custodyStatus;
-}
-
/**
* Whether or not should run the logic before checking the transaction when checking pending transactions.
*
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index f07c1db91bdf..fbcf291e4611 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -240,7 +240,6 @@ import {
afterTransactionSign as afterTransactionSignMMI,
beforeCheckPendingTransaction as beforeCheckPendingTransactionMMI,
beforeTransactionPublish as beforeTransactionPublishMMI,
- beforeTransactionApproveOnInit as beforeApproveOnInitMMI,
getAdditionalSignArguments as getAdditionalSignArgumentsMMI,
} from './lib/transaction/mmi-hooks';
///: END:ONLY_INCLUDE_IF
@@ -1764,7 +1763,6 @@ export default class MetamaskController extends EventEmitter {
),
beforeCheckPendingTransaction:
beforeCheckPendingTransactionMMI.bind(this),
- beforeApproveOnInit: beforeApproveOnInitMMI.bind(this),
beforePublish: beforeTransactionPublishMMI.bind(this),
getAdditionalSignArguments: getAdditionalSignArgumentsMMI.bind(this),
///: END:ONLY_INCLUDE_IF
diff --git a/package.json b/package.json
index c95b55be0b83..29c066a67d57 100644
--- a/package.json
+++ b/package.json
@@ -228,7 +228,6 @@
"@trezor/schema-utils@npm:1.0.2": "patch:@trezor/schema-utils@npm%3A1.0.2#~/.yarn/patches/@trezor-schema-utils-npm-1.0.2-7dd48689b2.patch",
"lavamoat-core@npm:^15.1.1": "patch:lavamoat-core@npm%3A15.1.1#~/.yarn/patches/lavamoat-core-npm-15.1.1-51fbe39988.patch",
"@metamask/snaps-sdk": "^6.2.1",
- "@metamask/transaction-controller": "^34.0.0",
"@swc/types@0.1.5": "^0.1.6",
"@babel/runtime@npm:^7.7.6": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch",
"@babel/runtime@npm:^7.9.2": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch",
@@ -266,6 +265,7 @@
"@metamask/nonce-tracker@npm:^5.0.0": "patch:@metamask/nonce-tracker@npm%3A5.0.0#~/.yarn/patches/@metamask-nonce-tracker-npm-5.0.0-d81478218e.patch",
"@metamask/keyring-controller@npm:^17.1.0": "patch:@metamask/keyring-controller@npm%3A17.1.1#~/.yarn/patches/@metamask-keyring-controller-npm-17.1.1-098cb41930.patch",
"@trezor/connect-web@npm:^9.1.11": "patch:@trezor/connect-web@npm%3A9.3.0#~/.yarn/patches/@trezor-connect-web-npm-9.3.0-040ab10d9a.patch",
+ "@metamask/transaction-controller@npm:^34.0.0": "patch:@metamask/transaction-controller@npm%3A34.0.0#~/.yarn/patches/@metamask-transaction-controller-npm-34.0.0-8bdfa87aaf.patch",
"path-to-regexp": "1.9.0"
},
"dependencies": {
@@ -356,7 +356,7 @@
"@metamask/snaps-rpc-methods": "^11.0.0",
"@metamask/snaps-sdk": "^6.2.1",
"@metamask/snaps-utils": "^8.0.1",
- "@metamask/transaction-controller": "^34.0.0",
+ "@metamask/transaction-controller": "patch:@metamask/transaction-controller@npm%3A34.0.0#~/.yarn/patches/@metamask-transaction-controller-npm-34.0.0-8bdfa87aaf.patch",
"@metamask/user-operation-controller": "^13.0.0",
"@metamask/utils": "^8.2.1",
"@ngraveio/bc-ur": "^1.1.12",
diff --git a/test/e2e/fixture-builder.js b/test/e2e/fixture-builder.js
index cbccac2eab0d..76eb86e12ad1 100644
--- a/test/e2e/fixture-builder.js
+++ b/test/e2e/fixture-builder.js
@@ -8,7 +8,7 @@ const { NetworkStatus } = require('@metamask/network-controller');
const { CHAIN_IDS, NETWORK_TYPES } = require('../../shared/constants/network');
const { SMART_CONTRACTS } = require('./seeder/smart-contracts');
-const { DAPP_URL, DAPP_ONE_URL, ACCOUNT_1 } = require('./helpers');
+const { DAPP_URL, DAPP_ONE_URL } = require('./helpers');
const { DEFAULT_FIXTURE_ACCOUNT, ERC_4337_ACCOUNT } = require('./constants');
const {
defaultFixture,
@@ -239,6 +239,22 @@ class FixtureBuilder {
return this;
}
+ withNetworkControllerOnOptimism() {
+ return this.withNetworkController({
+ networkConfigurations: {
+ networkConfigurationId: {
+ chainId: CHAIN_IDS.OPTIMISM,
+ nickname: 'Localhost 8545',
+ rpcPrefs: {},
+ rpcUrl: 'https://mainnet.infura.io',
+ ticker: 'ETH',
+ networkConfigurationId: 'networkConfigurationId',
+ id: 'networkConfigurationId',
+ },
+ },
+ });
+ }
+
withNetworkControllerDoubleGanache() {
return this.withNetworkController({
networkConfigurations: {
@@ -809,587 +825,6 @@ class FixtureBuilder {
return this;
}
- withTransactionControllerMultipleTransactions() {
- return this.withTransactionController({
- transactions: {
- '7087d1d7-f0e8-4c0f-a903-6d9daa392baf': {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- history: [
- {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- id: '7087d1d7-f0e8-4c0f-a903-6d9daa392baf',
- loadingDefaults: true,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545991949,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- [
- {
- note: 'Added new unapproved transaction.',
- op: 'replace',
- path: '/loadingDefaults',
- timestamp: 1631545992244,
- value: false,
- },
- {
- op: 'add',
- path: '/simulationData',
- value: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- note: 'TransactionController#updateSimulationData - Update simulation data',
- timestamp: 1631545992244,
- },
- ],
- ],
- simulationData: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- id: '7087d1d7-f0e8-4c0f-a903-6d9daa392baf',
- loadingDefaults: false,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545991949,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- '6eab4240-3762-4581-abc5-cd91eab6964e': {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- history: [
- {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- id: '6eab4240-3762-4581-abc5-cd91eab6964e',
- loadingDefaults: true,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545994578,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- [
- {
- note: 'Added new unapproved transaction.',
- op: 'replace',
- path: '/loadingDefaults',
- timestamp: 1631545994695,
- value: false,
- },
- {
- op: 'add',
- path: '/simulationData',
- value: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- note: 'TransactionController#updateSimulationData - Update simulation data',
- timestamp: 1631545992244,
- },
- ],
- ],
- simulationData: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- id: '6eab4240-3762-4581-abc5-cd91eab6964e',
- loadingDefaults: false,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545994578,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- 'c15eee26-11d6-4914-a70e-36ef9a3bcacb': {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- history: [
- {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- id: 'c15eee26-11d6-4914-a70e-36ef9a3bcacb',
- loadingDefaults: true,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545996673,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- [
- {
- note: 'Added new unapproved transaction.',
- op: 'replace',
- path: '/loadingDefaults',
- timestamp: 1631545996678,
- value: false,
- },
- {
- op: 'add',
- path: '/simulationData',
- value: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- note: 'TransactionController#updateSimulationData - Update simulation data',
- timestamp: 1631545992244,
- },
- ],
- ],
- simulationData: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- id: 'c15eee26-11d6-4914-a70e-36ef9a3bcacb',
- loadingDefaults: false,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545996673,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- 'dfa9e5ad-d069-46b1-976e-a23734971d87': {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- history: [
- {
- chainId: CHAIN_IDS.LOCALHOST,
- dappSuggestedGasFees: {
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- },
- id: 'dfa9e5ad-d069-46b1-976e-a23734971d87',
- loadingDefaults: true,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545998675,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- [
- {
- note: 'Added new unapproved transaction.',
- op: 'replace',
- path: '/loadingDefaults',
- timestamp: 1631545998677,
- value: false,
- },
- {
- op: 'add',
- path: '/simulationData',
- value: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- note: 'TransactionController#updateSimulationData - Update simulation data',
- timestamp: 1631545992244,
- },
- ],
- ],
- simulationData: {
- error: {
- code: 'disabled',
- message: 'Simulation disabled',
- },
- tokenBalanceChanges: [],
- },
- id: 'dfa9e5ad-d069-46b1-976e-a23734971d87',
- loadingDefaults: false,
- origin: 'https://metamask.github.io',
- status: 'unapproved',
- time: 1631545998675,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x5208',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318c334780961fb129d2a6c30d0763d9a5c970',
- value: '0x29a2241af62c0000',
- },
- type: 'simpleSend',
- },
- },
- });
- }
-
- withTransactionControllerTypeOneTransaction() {
- return this.withTransactionController({
- transactions: {
- '13a01e77-a368-4bb9-aba9-e7435580e3b9': {
- chainId: CHAIN_IDS.LOCALHOST,
- history: [
- {
- chainId: CHAIN_IDS.LOCALHOST,
- id: '13a01e77-a368-4bb9-aba9-e7435580e3b9',
- loadingDefaults: true,
- origin: 'metamask',
- status: 'unapproved',
- time: 1617228030067,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x61a8',
- gasPrice: '0x2540be400',
- to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
- value: '0xde0b6b3a7640000',
- },
- type: 'simpleSend',
- },
- [
- {
- note: 'Added new unapproved transaction.',
- op: 'replace',
- path: '/loadingDefaults',
- timestamp: 1617228030069,
- value: false,
- },
- ],
- ],
- id: '13a01e77-a368-4bb9-aba9-e7435580e3b9',
- loadingDefaults: false,
- origin: 'metamask',
- primaryTransaction: {
- chainId: CHAIN_IDS.LOCALHOST,
- id: '13a01e77-a368-4bb9-aba9-e7435580e3b9',
- loadingDefaults: true,
- origin: 'metamask',
- status: 'unapproved',
- time: 1617228030067,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x61a8',
- gasPrice: '0x2540be400',
- to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
- value: '0xde0b6b3a7640000',
- },
- type: 'sentEther',
- },
- status: 'unapproved',
- time: 1617228030067,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x61a8',
- gasPrice: '0x2540be400',
- to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
- value: '0xde0b6b3a7640000',
- },
- type: 'simpleSend',
- },
- },
- });
- }
-
- withTransactionControllerTypeTwoTransaction() {
- return this.withTransactionController({
- transactions: {
- '13a01e77-a368-4bb9-aba9-e7435580e3b9': {
- chainId: CHAIN_IDS.LOCALHOST,
- history: [
- {
- chainId: CHAIN_IDS.LOCALHOST,
- id: '13a01e77-a368-4bb9-aba9-e7435580e3b9',
- loadingDefaults: true,
- origin: 'metamask',
- status: 'unapproved',
- time: 1617228030067,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x61a8',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
- type: '0x2',
- value: '0xde0b6b3a7640000',
- },
- type: 'simpleSend',
- },
- [
- {
- note: 'Added new unapproved transaction.',
- op: 'replace',
- path: '/loadingDefaults',
- timestamp: 1617228030069,
- value: false,
- },
- ],
- ],
- id: '13a01e77-a368-4bb9-aba9-e7435580e3b9',
- loadingDefaults: false,
- origin: 'metamask',
- primaryTransaction: {
- chainId: CHAIN_IDS.LOCALHOST,
- id: '13a01e77-a368-4bb9-aba9-e7435580e3b9',
- loadingDefaults: true,
- origin: 'metamask',
- status: 'unapproved',
- time: 1617228030067,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x61a8',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
- type: '0x2',
- value: '0xde0b6b3a7640000',
- },
- type: 'sentEther',
- },
- status: 'unapproved',
- time: 1617228030067,
- txParams: {
- from: '0x5cfe73b6021e818b776b421b1c4db2474086a7e1',
- gas: '0x61a8',
- maxFeePerGas: '0x59682f0c',
- maxPriorityFeePerGas: '0x59682f00',
- to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
- type: '0x2',
- value: '0xde0b6b3a7640000',
- },
- type: 'simpleSend',
- },
- },
- });
- }
-
- withTransactionControllerOPLayer2Transaction() {
- const FROM_ADDRESS = ACCOUNT_1;
- const TRANSACTION_ID = 'f0fc75d0-181d-11ef-9546-8b2366f13afd';
- const TRANSACTION_TYPE = 'contractInteraction';
- const TEST_NETWORK_CLIENT_ID = 'networkConfigurationId';
-
- return this.withTransactionController({
- transactions: {
- [TRANSACTION_ID]: {
- actionId: 3577139671,
- chainId: '0xa',
- dappSuggestedGasFees: { gas: '0x31f10' },
- defaultGasEstimates: {
- estimateType: 'dappSuggested',
- gas: '0x31f10',
- maxFeePerGas: '0x3b014b3',
- maxPriorityFeePerGas: '0x3b014b3',
- },
- gasFeeEstimates: { gasPrice: '0x3b202d0', type: 'eth_gasPrice' },
- gasFeeEstimatesLoaded: true,
- history: [
- {
- actionId: 3577139671,
- chainId: '0xa',
- dappSuggestedGasFees: { gas: '0x31f10' },
- defaultGasEstimates: {
- estimateType: 'dappSuggested',
- gas: '0x31f10',
- maxFeePerGas: '0x3b014b3',
- maxPriorityFeePerGas: '0x3b014b3',
- },
- id: TRANSACTION_ID,
- layer1GasFee: '0x175283ae57',
- networkClientId: TEST_NETWORK_CLIENT_ID,
- origin: 'https://metamask.github.io',
- securityAlertResponse: {
- reason: 'loading',
- result_type: 'validation_in_progress',
- securityAlertId: '30626504-0069-4278-9e2e-3d7fba2e6aef',
- },
- sendFlowHistory: [],
- status: 'unapproved',
- time: 1716370234797,
- txParams: {
- data: '0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000808190555061023b806100686000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632e1a7d4d1461005c5780638da5cb5b1461009d578063d0e30db0146100f4575b600080fd5b34801561006857600080fd5b5061008760048036038101908080359060200190929190505050610112565b6040518082815260200191505060405180910390f35b3480156100a957600080fd5b506100b26101d0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100fc6101f6565b6040518082815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561017057600080fd5b8160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501580156101c5573d6000803e3d6000fd5b506000549050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003460008082825401925050819055506000549050905600a165627a7a72305820f237db3ec816a52589d82512117bc85bc08d3537683ffeff9059108caf3e5d400029',
- from: FROM_ADDRESS,
- gas: '0x31f10',
- maxFeePerGas: '0x3b014b3',
- maxPriorityFeePerGas: '0x3b014b3',
- value: '0x0',
- },
- type: TRANSACTION_TYPE,
- userEditedGasLimit: false,
- userFeeLevel: 'dappSuggested',
- verifiedOnBlockchain: false,
- },
- [
- {
- note: 'TransactionController#updateSimulationData - Update simulation data',
- op: 'add',
- path: '/simulationData',
- timestamp: 1716370235743,
- value: {
- error: { code: 'disabled', message: 'Simulation disabled' },
- tokenBalanceChanges: [],
- },
- },
- ],
- [
- {
- note: 'TransactionController:updatesecurityAlertResponse - securityAlertResponse updated',
- op: 'replace',
- path: '/securityAlertResponse/result_type',
- timestamp: 1716370236091,
- value: 'Benign',
- },
- {
- op: 'replace',
- path: '/securityAlertResponse/reason',
- value: '',
- },
- {
- op: 'add',
- path: '/securityAlertResponse/description',
- value: '',
- },
- { op: 'add', path: '/securityAlertResponse/features', value: [] },
- {
- op: 'add',
- path: '/securityAlertResponse/block',
- value: 120385722,
- },
- {
- op: 'add',
- path: '/gasFeeEstimates',
- value: { gasPrice: '0x3b014b3', type: 'eth_gasPrice' },
- },
- { op: 'add', path: '/gasFeeEstimatesLoaded', value: true },
- ],
- ],
- id: TRANSACTION_ID,
- layer1GasFee: '0x19fdabf615',
- networkClientId: TEST_NETWORK_CLIENT_ID,
- origin: 'https://metamask.github.io',
- securityAlertResponse: {
- block: 120385722,
- description: '',
- features: [],
- reason: '',
- result_type: 'Benign',
- securityAlertId: '30626504-0069-4278-9e2e-3d7fba2e6aef',
- },
- sendFlowHistory: [],
- simulationData: {
- error: { code: 'disabled', message: 'Simulation disabled' },
- tokenBalanceChanges: [],
- },
- status: 'unapproved',
- time: 1716370234797,
- txParams: {
- data: '0x608060405234801561001057600080fd5b5033600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000808190555061023b806100686000396000f300608060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632e1a7d4d1461005c5780638da5cb5b1461009d578063d0e30db0146100f4575b600080fd5b34801561006857600080fd5b5061008760048036038101908080359060200190929190505050610112565b6040518082815260200191505060405180910390f35b3480156100a957600080fd5b506100b26101d0565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100fc6101f6565b6040518082815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561017057600080fd5b8160008082825403925050819055503373ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f193505050501580156101c5573d6000803e3d6000fd5b506000549050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60003460008082825401925050819055506000549050905600a165627a7a72305820f237db3ec816a52589d82512117bc85bc08d3537683ffeff9059108caf3e5d400029',
- from: FROM_ADDRESS,
- gas: '0x31f10',
- maxFeePerGas: '0x3b014b3',
- maxPriorityFeePerGas: '0x3b014b3',
- value: '0x0',
- },
- type: TRANSACTION_TYPE,
- userEditedGasLimit: false,
- userFeeLevel: 'dappSuggested',
- verifiedOnBlockchain: false,
- },
- },
- });
- }
-
withTransactionControllerApprovedTransaction() {
return this.withTransactionController({
transactions: {
diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js
index 092e4c64042e..167ac13a0e18 100644
--- a/test/e2e/helpers.js
+++ b/test/e2e/helpers.js
@@ -19,6 +19,7 @@ const { SMART_CONTRACTS } = require('./seeder/smart-contracts');
const {
ERC_4337_ACCOUNT,
DEFAULT_GANACHE_ETH_BALANCE_DEC,
+ DEFAULT_FIXTURE_ACCOUNT,
} = require('./constants');
const {
getServerMochaToBackground,
@@ -707,6 +708,18 @@ const createDappTransaction = async (driver, transaction) => {
);
};
+const createDappTransactionTypeTwo = async (driver) => {
+ await createDappTransaction(driver, {
+ data: '0x',
+ from: DEFAULT_FIXTURE_ACCOUNT,
+ maxFeePerGas: '0x0',
+ maxPriorityFeePerGas: '0x0',
+ to: '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
+ value: '0x38d7ea4c68000',
+ type: '0x2',
+ });
+};
+
const switchToOrOpenDapp = async (
driver,
contract = null,
@@ -849,6 +862,7 @@ const sendTransaction = async (
recipientAddress,
quantity,
isAsyncFlow = false,
+ skipConfirm = false,
) => {
await openActionMenuAndStartSendFlow(driver);
await driver.fill('[data-testid="ens-input"]', recipientAddress);
@@ -858,10 +872,13 @@ const sendTransaction = async (
text: 'Continue',
tag: 'button',
});
- await driver.clickElement({
- text: 'Confirm',
- tag: 'button',
- });
+
+ if (skipConfirm !== true) {
+ await driver.clickElement({
+ text: 'Confirm',
+ tag: 'button',
+ });
+ }
// the default is to do this block, but if we're testing an async flow, it would get stuck here
if (!isAsyncFlow) {
@@ -871,6 +888,19 @@ const sendTransaction = async (
}
};
+const createInternalTransaction = async (driver) => {
+ // Firefox has incorrect balance if send flow started too quickly.
+ await driver.delay(1000);
+
+ await sendTransaction(
+ driver,
+ '0x2f318C334780961FB129D2a6c30D0763d9a5C970',
+ '1',
+ true,
+ true,
+ );
+};
+
const findAnotherAccountFromAccountList = async (
driver,
itemNumber,
@@ -1276,4 +1306,6 @@ module.exports = {
getSelectedAccountAddress,
tempToggleSettingRedesignedConfirmations,
openMenuSafe,
+ createDappTransactionTypeTwo,
+ createInternalTransaction,
};
diff --git a/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts b/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts
index 3d28afff5790..fc6ca9e2ff4e 100644
--- a/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts
+++ b/test/e2e/tests/confirmations/transactions/contract-interaction-redesign.spec.ts
@@ -1,6 +1,9 @@
/* eslint-disable @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */
-import { openDapp, unlockWallet } from '../../../helpers';
-import GanacheContractAddressRegistry from '../../../seeder/ganache-contract-address-registry';
+import { Mockttp } from 'mockttp';
+import { createDappTransaction, unlockWallet } from '../../../helpers';
+import { Driver } from '../../../webdriver/driver';
+import { MockedEndpoint } from '../../../mock-e2e';
+import { DEFAULT_FIXTURE_ACCOUNT } from '../../../constants';
import {
assertAdvancedGasDetails,
confirmDepositTransaction,
@@ -90,8 +93,9 @@ describe('Confirmation Redesign Contract Interaction Component', function () {
redesignedConfirmationsEnabled: true,
isRedesignedConfirmationsDeveloperEnabled: true,
},
+ useTransactionSimulations: false,
})
- .withTransactionControllerOPLayer2Transaction()
+ .withNetworkControllerOnOptimism()
.build(),
ganacheOptions: {
...defaultGanacheOptionsForType2Transactions,
@@ -100,19 +104,13 @@ describe('Confirmation Redesign Contract Interaction Component', function () {
},
smartContract,
title: this.test?.fullTitle(),
+ testSpecificMock: mockOptimismOracle,
},
- async ({ driver, contractRegistry }: TestSuiteArguments) => {
+ async ({ driver }: TestSuiteArguments) => {
await unlockWallet(driver);
+ await createLayer2Transaction(driver);
- const contractAddress = await (
- contractRegistry as GanacheContractAddressRegistry
- ).getContractAddress(smartContract);
-
- await openDapp(driver, contractAddress);
-
- await driver.switchToWindowWithTitle(
- WINDOW_TITLES.ExtensionInFullScreenView,
- );
+ await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
await toggleAdvancedDetails(driver);
@@ -279,3 +277,38 @@ describe('Confirmation Redesign Contract Interaction Component', function () {
});
});
});
+
+async function createLayer2Transaction(driver: Driver) {
+ await createDappTransaction(driver, {
+ data: '0x1234',
+ from: DEFAULT_FIXTURE_ACCOUNT,
+ to: '0x581c3C1A2A4EBDE2A0Df29B5cf4c116E42945947',
+ gas: '0x31f10',
+ maxFeePerGas: '0x3b014b3',
+ maxPriorityFeePerGas: '0x3b014b3',
+ });
+}
+
+async function mockOptimismOracle(
+ mockServer: Mockttp,
+): Promise {
+ return [
+ await mockServer
+ .forPost(/infura/u)
+ .withJsonBodyIncluding({
+ method: 'eth_call',
+ params: [{ to: '0x420000000000000000000000000000000000000f' }],
+ })
+ .thenCallback(() => {
+ return {
+ statusCode: 200,
+ json: {
+ jsonrpc: '2.0',
+ id: '1111111111111111',
+ result:
+ '0x0000000000000000000000000000000000000000000000000000000c895f9d79',
+ },
+ };
+ }),
+ ];
+}
diff --git a/test/e2e/tests/confirmations/transactions/shared.ts b/test/e2e/tests/confirmations/transactions/shared.ts
index bf3063e3809a..fe85a2e3f851 100644
--- a/test/e2e/tests/confirmations/transactions/shared.ts
+++ b/test/e2e/tests/confirmations/transactions/shared.ts
@@ -66,7 +66,6 @@ export async function createDepositTransaction(driver: Driver) {
export async function confirmDepositTransaction(driver: Driver) {
await driver.waitUntilXWindowHandles(3);
-
await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
await driver.waitForSelector({
@@ -74,7 +73,6 @@ export async function confirmDepositTransaction(driver: Driver) {
text: 'Transaction request',
});
- await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
await toggleAdvancedDetails(driver);
await driver.waitForSelector({
diff --git a/test/e2e/tests/transaction/edit-gas-fee.spec.js b/test/e2e/tests/transaction/edit-gas-fee.spec.js
index 5a1f32a56411..07944e0e973c 100644
--- a/test/e2e/tests/transaction/edit-gas-fee.spec.js
+++ b/test/e2e/tests/transaction/edit-gas-fee.spec.js
@@ -5,6 +5,7 @@ const {
unlockWallet,
generateGanacheOptions,
WINDOW_TITLES,
+ createInternalTransaction,
} = require('../../helpers');
const FixtureBuilder = require('../../fixture-builder');
@@ -12,20 +13,18 @@ describe('Editing Confirm Transaction', function () {
it('allows selecting high, medium, low gas estimates on edit gas fee popover @no-mmi', async function () {
await withFixtures(
{
- fixtures: new FixtureBuilder()
- .withTransactionControllerTypeTwoTransaction()
- .build(),
+ fixtures: new FixtureBuilder().build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
},
async ({ driver }) => {
await unlockWallet(driver);
+ await createInternalTransaction(driver);
- const transactionAmounts = await driver.findElements(
- '.currency-display-component__text',
- );
- const transactionAmount = transactionAmounts[0];
- assert.equal(await transactionAmount.getText(), '1');
+ await driver.findElement({
+ css: '.currency-display-component__text',
+ text: '1',
+ });
// update estimates to high
await driver.clickElement('[data-testid="edit-gas-fee-icon"]');
@@ -87,20 +86,18 @@ describe('Editing Confirm Transaction', function () {
it('allows accessing advance gas fee popover from edit gas fee popover', async function () {
await withFixtures(
{
- fixtures: new FixtureBuilder()
- .withTransactionControllerTypeTwoTransaction()
- .build(),
+ fixtures: new FixtureBuilder().build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
},
async ({ driver }) => {
await unlockWallet(driver);
+ await createInternalTransaction(driver);
- const transactionAmounts = await driver.findElements(
- '.currency-display-component__text',
- );
- const transactionAmount = transactionAmounts[0];
- assert.equal(await transactionAmount.getText(), '1');
+ await driver.findElement({
+ css: '.currency-display-component__text',
+ text: '1',
+ });
// update estimates to high
await driver.clickElement('[data-testid="edit-gas-fee-icon"]');
diff --git a/test/e2e/tests/transaction/navigate-transactions.spec.js b/test/e2e/tests/transaction/navigate-transactions.spec.js
index 12c1144d5472..151e22ba55b9 100644
--- a/test/e2e/tests/transaction/navigate-transactions.spec.js
+++ b/test/e2e/tests/transaction/navigate-transactions.spec.js
@@ -1,104 +1,52 @@
-const { strict: assert } = require('assert');
const {
withFixtures,
openDapp,
locateAccountBalanceDOM,
unlockWallet,
generateGanacheOptions,
+ WINDOW_TITLES,
+ createDappTransactionTypeTwo,
} = require('../../helpers');
const FixtureBuilder = require('../../fixture-builder');
+const TRANSACTION_COUNT = 4;
+
describe('Navigate transactions', function () {
it('should navigate the unapproved transactions', async function () {
await withFixtures(
{
fixtures: new FixtureBuilder()
.withPreferencesControllerTxSimulationsDisabled()
- .withTransactionControllerMultipleTransactions()
+ .withPermissionControllerConnectedToTestDapp()
.build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
+ dapp: true,
},
async ({ driver }) => {
await unlockWallet(driver);
+ await createMultipleTransactions(driver, TRANSACTION_COUNT);
- // Wait until total amount is loaded to mitigate flakiness on reject
- await driver.findElement({
- tag: 'span',
- text: '3.0000315',
- });
+ await clickNextPage(driver);
+ await expectPageNumber(driver, 2, 4);
- // navigate transactions
- await driver.clickElement('[data-testid="next-page"]');
- let navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- let navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('2 of 4'),
- true,
- 'changed transaction right',
- );
- await driver.clickElement('[data-testid="next-page"]');
- navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('3 of 4'),
- true,
- 'changed transaction right',
- );
- await driver.clickElement('[data-testid="next-page"]');
- navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('4 of 4'),
- true,
- 'changed transaction right',
- );
- await driver.clickElement('[data-testid="first-page"]');
- navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('1 of 4'),
- true,
- 'navigate to first transaction',
- );
- await driver.clickElement('[data-testid="last-page"]');
- navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('4 of 4'),
- true,
- 'navigate to last transaction',
- );
- await driver.clickElement('[data-testid="previous-page"]');
- navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('3 of 4'),
- true,
- 'changed transaction left',
- );
- await driver.clickElement('[data-testid="previous-page"]');
- navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('2 of 4'),
- true,
- 'changed transaction left',
- );
+ await clickNextPage(driver);
+ await expectPageNumber(driver, 3, 4);
+
+ await clickNextPage(driver);
+ await expectPageNumber(driver, 4, 4);
+
+ await clickFirstPage(driver);
+ await expectPageNumber(driver, 1, 4);
+
+ await clickLastPage(driver);
+ await expectPageNumber(driver, 4, 4);
+
+ await clickPreviousPage(driver);
+ await expectPageNumber(driver, 3, 4);
+
+ await clickPreviousPage(driver);
+ await expectPageNumber(driver, 2, 4);
},
);
});
@@ -110,48 +58,26 @@ describe('Navigate transactions', function () {
fixtures: new FixtureBuilder()
.withPermissionControllerConnectedToTestDapp()
.withPreferencesControllerTxSimulationsDisabled()
- .withTransactionControllerMultipleTransactions()
.build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
},
async ({ driver }) => {
await unlockWallet(driver);
+ await createMultipleTransactions(driver, TRANSACTION_COUNT);
- // Wait until total amount is loaded to mitigate flakiness on reject
- await driver.findElement({
- tag: 'span',
- text: '3.0000315',
- });
+ await clickNextPage(driver);
+ await expectPageNumber(driver, 2, 4);
- await driver.clickElement('[data-testid="next-page"]');
- let navigationElement = await driver.findElement(
- '.confirm-page-container-navigation',
- );
- let navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('2 of 4'),
- true,
- 'second transaction in focus',
+ await driver.switchToWindowWithTitle(
+ WINDOW_TITLES.ExtensionInFullScreenView,
);
- // add transaction
await openDapp(driver);
await driver.clickElement({ text: 'Send', tag: 'button' });
- await driver.waitUntilXWindowHandles(3);
- const windowHandles = await driver.getAllWindowHandles();
- const extension = windowHandles[0];
- await driver.switchToWindow(extension);
- navigationElement = await driver.waitForSelector({
- css: '.confirm-page-container-navigation',
- text: '2 of 5',
- });
- navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('2 of 5'),
- true,
- 'correct (same) transaction in focus',
- );
+ await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
+
+ await expectPageNumber(driver, 2, 5);
},
);
});
@@ -161,32 +87,20 @@ describe('Navigate transactions', function () {
{
fixtures: new FixtureBuilder()
.withPreferencesControllerTxSimulationsDisabled()
- .withTransactionControllerMultipleTransactions()
+ .withPermissionControllerConnectedToTestDapp()
.build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
+ dapp: true,
},
async ({ driver }) => {
await unlockWallet(driver);
-
- // Wait until total amount is loaded to mitigate flakiness on reject
- await driver.findElement({
- tag: 'span',
- text: '3.0000315',
- });
+ await createMultipleTransactions(driver, TRANSACTION_COUNT);
// reject transaction
await driver.clickElement({ text: 'Reject', tag: 'button' });
- const navigationElement = await driver.waitForSelector({
- css: '.confirm-page-container-navigation',
- text: '1 of 3',
- });
- const navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('1 of 3'),
- true,
- 'transaction rejected',
- );
+
+ await expectPageNumber(driver, 1, 3);
},
);
});
@@ -196,32 +110,20 @@ describe('Navigate transactions', function () {
{
fixtures: new FixtureBuilder()
.withPreferencesControllerTxSimulationsDisabled()
- .withTransactionControllerMultipleTransactions()
+ .withPermissionControllerConnectedToTestDapp()
.build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
+ dapp: true,
},
async ({ driver }) => {
await unlockWallet(driver);
-
- // Wait until total amount is loaded to mitigate flakiness on reject
- await driver.findElement({
- tag: 'span',
- text: '3.0000315',
- });
+ await createMultipleTransactions(driver, TRANSACTION_COUNT);
// confirm transaction
await driver.clickElement({ text: 'Confirm', tag: 'button' });
- const navigationElement = await driver.waitForSelector({
- css: '.confirm-page-container-navigation',
- text: '1 of 3',
- });
- const navigationText = await navigationElement.getText();
- assert.equal(
- navigationText.includes('1 of 3'),
- true,
- 'transaction confirmed',
- );
+
+ await expectPageNumber(driver, 1, 3);
},
);
});
@@ -231,25 +133,61 @@ describe('Navigate transactions', function () {
{
fixtures: new FixtureBuilder()
.withPreferencesControllerTxSimulationsDisabled()
- .withTransactionControllerMultipleTransactions()
+ .withPermissionControllerConnectedToTestDapp()
.build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
+ dapp: true,
},
async ({ driver, ganacheServer }) => {
await unlockWallet(driver);
-
- // Wait until total amount is loaded to mitigate flakiness on reject
- await driver.findElement({
- tag: 'span',
- text: '3.0000315',
- });
+ await createMultipleTransactions(driver, TRANSACTION_COUNT);
// reject transactions
await driver.clickElement({ text: 'Reject 4', tag: 'a' });
await driver.clickElement({ text: 'Reject all', tag: 'button' });
+ await driver.switchToWindowWithTitle(
+ WINDOW_TITLES.ExtensionInFullScreenView,
+ );
await locateAccountBalanceDOM(driver, ganacheServer);
},
);
});
});
+
+async function createMultipleTransactions(driver, count) {
+ for (let i = 0; i < count; i++) {
+ await createDappTransactionTypeTwo(driver);
+ }
+
+ await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
+
+ // Wait until total amount is loaded to mitigate flakiness on reject
+ await driver.findElement({
+ tag: 'span',
+ text: '0.001',
+ });
+}
+
+async function clickFirstPage(driver) {
+ await driver.clickElement('[data-testid="first-page"]');
+}
+
+async function clickLastPage(driver) {
+ await driver.clickElement('[data-testid="last-page"]');
+}
+
+async function clickNextPage(driver) {
+ await driver.clickElement('[data-testid="next-page"]');
+}
+
+async function clickPreviousPage(driver) {
+ await driver.clickElement('[data-testid="previous-page"]');
+}
+
+async function expectPageNumber(driver, current, total) {
+ await driver.findElement({
+ css: '.confirm-page-container-navigation',
+ text: `${current} of ${total}`,
+ });
+}
diff --git a/test/e2e/tests/transaction/send-edit.spec.js b/test/e2e/tests/transaction/send-edit.spec.js
index a3665bd33591..6e372ad2d64a 100644
--- a/test/e2e/tests/transaction/send-edit.spec.js
+++ b/test/e2e/tests/transaction/send-edit.spec.js
@@ -4,6 +4,7 @@ const {
withFixtures,
unlockWallet,
generateGanacheOptions,
+ createInternalTransaction,
} = require('../../helpers');
const FixtureBuilder = require('../../fixture-builder');
@@ -11,22 +12,23 @@ describe('Editing Confirm Transaction', function () {
it('goes back from confirm page to edit eth value, gas price and gas limit', async function () {
await withFixtures(
{
- fixtures: new FixtureBuilder()
- .withTransactionControllerTypeOneTransaction()
- .build(),
+ fixtures: new FixtureBuilder().build(),
ganacheOptions: defaultGanacheOptions,
title: this.test.fullTitle(),
},
async ({ driver }) => {
await unlockWallet(driver);
- const transactionAmounts = await driver.findElements(
- '.currency-display-component__text',
- );
- const transactionAmount = transactionAmounts[0];
- assert.equal(await transactionAmount.getText(), '1');
+ await createInternalTransaction(driver);
+
+ await driver.findElement({
+ css: '.currency-display-component__text',
+ text: '1',
+ });
- const transactionFee = transactionAmounts[1];
- assert.equal(await transactionFee.getText(), '0.00025');
+ await driver.findElement({
+ css: '.currency-display-component__text',
+ text: '1.000042',
+ });
await driver.clickElement(
'.confirm-page-container-header__back-button',
@@ -85,22 +87,23 @@ describe('Editing Confirm Transaction', function () {
it('goes back from confirm page to edit eth value, baseFee, priorityFee and gas limit - 1559 V2', async function () {
await withFixtures(
{
- fixtures: new FixtureBuilder()
- .withTransactionControllerTypeTwoTransaction()
- .build(),
+ fixtures: new FixtureBuilder().build(),
ganacheOptions: generateGanacheOptions({ hardfork: 'london' }),
title: this.test.fullTitle(),
},
async ({ driver }) => {
await unlockWallet(driver);
- const transactionAmounts = await driver.findElements(
- '.currency-display-component__text',
- );
- const transactionAmount = transactionAmounts[0];
- assert.equal(await transactionAmount.getText(), '1');
+ await createInternalTransaction(driver);
+
+ await driver.findElement({
+ css: '.currency-display-component__text',
+ text: '1',
+ });
- const transactionFee = transactionAmounts[1];
- assert.equal(await transactionFee.getText(), '0.0000375');
+ await driver.findElement({
+ css: '.currency-display-component__text',
+ text: '1.00043983',
+ });
await driver.clickElement(
'.confirm-page-container-header__back-button',
diff --git a/yarn.lock b/yarn.lock
index c67922eaa24d..7bbc4c2a1cd3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6505,7 +6505,7 @@ __metadata:
languageName: node
linkType: hard
-"@metamask/transaction-controller@npm:^34.0.0":
+"@metamask/transaction-controller@npm:34.0.0":
version: 34.0.0
resolution: "@metamask/transaction-controller@npm:34.0.0"
dependencies:
@@ -6542,6 +6542,43 @@ __metadata:
languageName: node
linkType: hard
+"@metamask/transaction-controller@patch:@metamask/transaction-controller@npm%3A34.0.0#~/.yarn/patches/@metamask-transaction-controller-npm-34.0.0-8bdfa87aaf.patch":
+ version: 34.0.0
+ resolution: "@metamask/transaction-controller@patch:@metamask/transaction-controller@npm%3A34.0.0#~/.yarn/patches/@metamask-transaction-controller-npm-34.0.0-8bdfa87aaf.patch::version=34.0.0&hash=82a387"
+ dependencies:
+ "@ethereumjs/common": "npm:^3.2.0"
+ "@ethereumjs/tx": "npm:^4.2.0"
+ "@ethereumjs/util": "npm:^8.1.0"
+ "@ethersproject/abi": "npm:^5.7.0"
+ "@ethersproject/contracts": "npm:^5.7.0"
+ "@ethersproject/providers": "npm:^5.7.0"
+ "@metamask/accounts-controller": "npm:^17.2.0"
+ "@metamask/approval-controller": "npm:^7.0.0"
+ "@metamask/base-controller": "npm:^6.0.0"
+ "@metamask/controller-utils": "npm:^11.0.0"
+ "@metamask/eth-query": "npm:^4.0.0"
+ "@metamask/gas-fee-controller": "npm:^18.0.0"
+ "@metamask/metamask-eth-abis": "npm:^3.1.1"
+ "@metamask/network-controller": "npm:^19.0.0"
+ "@metamask/nonce-tracker": "npm:^5.0.0"
+ "@metamask/rpc-errors": "npm:^6.2.1"
+ "@metamask/utils": "npm:^8.3.0"
+ async-mutex: "npm:^0.5.0"
+ bn.js: "npm:^5.2.1"
+ eth-method-registry: "npm:^4.0.0"
+ fast-json-patch: "npm:^3.1.1"
+ lodash: "npm:^4.17.21"
+ uuid: "npm:^8.3.2"
+ peerDependencies:
+ "@babel/runtime": ^7.23.9
+ "@metamask/accounts-controller": ^17.0.0
+ "@metamask/approval-controller": ^7.0.0
+ "@metamask/gas-fee-controller": ^18.0.0
+ "@metamask/network-controller": ^19.0.0
+ checksum: 10/96373e7703b506ffbba9cbbeec3f5cad07b73b238c02c727475254a9b4e492043d904de77203d80465f31ad6ce49e720c87a7ea6a9c64c7787b693ae64cc9f13
+ languageName: node
+ linkType: hard
+
"@metamask/user-operation-controller@npm:^13.0.0":
version: 13.0.0
resolution: "@metamask/user-operation-controller@npm:13.0.0"
@@ -25944,7 +25981,7 @@ __metadata:
"@metamask/snaps-utils": "npm:^8.0.1"
"@metamask/test-bundler": "npm:^1.0.0"
"@metamask/test-dapp": "npm:^8.4.0"
- "@metamask/transaction-controller": "npm:^34.0.0"
+ "@metamask/transaction-controller": "patch:@metamask/transaction-controller@npm%3A34.0.0#~/.yarn/patches/@metamask-transaction-controller-npm-34.0.0-8bdfa87aaf.patch"
"@metamask/user-operation-controller": "npm:^13.0.0"
"@metamask/utils": "npm:^8.2.1"
"@ngraveio/bc-ur": "npm:^1.1.12"
From a09d076095d06cfa2010ace41d9c495bc5048db7 Mon Sep 17 00:00:00 2001
From: Jyoti Puri
Date: Tue, 17 Sep 2024 18:22:19 +0530
Subject: [PATCH 26/43] fix(cherry-pick) : selector getKnownMethodData should
return empty object if user has opted out for using 4Byte Resolution (#27213)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
If user has toggled off **Decode smart contracts** setting he is not
able to approve ERC20. This is regression introduced recently.
## **Related issues**
Fixes: https://github.com/MetaMask/metamask-extension/issues/27188
## **Manual testing steps**
1. Toggle off setting "Decode smart contracts"
2. Try to approve an ERC 20
3. It should not throw error
## **Screenshots/Recordings**
https://github.com/user-attachments/assets/7f0fd8f9-3d97-4f4b-8e99-c694445ad929
## **Pre-merge author checklist**
- [X] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [X] I've completed the PR template to the best of my ability
- [X] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [X] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
.../components/confirm/info/hooks/useFourByte.test.ts | 6 +++---
.../info/shared/transaction-details/transaction-details.tsx | 2 +-
ui/selectors/selectors.js | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/ui/pages/confirmations/components/confirm/info/hooks/useFourByte.test.ts b/ui/pages/confirmations/components/confirm/info/hooks/useFourByte.test.ts
index 1c3d66570d8b..bdff31ac33e6 100644
--- a/ui/pages/confirmations/components/confirm/info/hooks/useFourByte.test.ts
+++ b/ui/pages/confirmations/components/confirm/info/hooks/useFourByte.test.ts
@@ -34,7 +34,7 @@ describe('useFourByte', () => {
expect(result.current.params).toEqual([]);
});
- it('returns undefined if resolution is turned off', () => {
+ it('returns empty object if resolution is turned off', () => {
const currentConfirmation = genUnapprovedContractInteractionConfirmation({
address: CONTRACT_INTERACTION_SENDER_ADDRESS,
txData: depositHexData,
@@ -54,7 +54,7 @@ describe('useFourByte', () => {
},
);
- expect(result.current).toBeUndefined();
+ expect(result.current).toEqual({});
});
it("returns undefined if it's not known even if resolution is enabled", () => {
@@ -75,6 +75,6 @@ describe('useFourByte', () => {
},
);
- expect(result.current).toBeUndefined();
+ expect(result.current).toEqual({});
});
});
diff --git a/ui/pages/confirmations/components/confirm/info/shared/transaction-details/transaction-details.tsx b/ui/pages/confirmations/components/confirm/info/shared/transaction-details/transaction-details.tsx
index 992e16f1baad..89bee67f4c51 100644
--- a/ui/pages/confirmations/components/confirm/info/shared/transaction-details/transaction-details.tsx
+++ b/ui/pages/confirmations/components/confirm/info/shared/transaction-details/transaction-details.tsx
@@ -70,7 +70,7 @@ const MethodDataRow = () => {
const methodData = useFourByte(currentConfirmation);
- if (!methodData) {
+ if (!methodData?.name) {
return null;
}
diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js
index e2f208149092..68187a1874b3 100644
--- a/ui/selectors/selectors.js
+++ b/ui/selectors/selectors.js
@@ -1236,7 +1236,7 @@ export function getKnownMethodData(state, data) {
const fourBytePrefix = prefixedData.slice(0, 10);
const { knownMethodData, use4ByteResolution } = state.metamask;
// If 4byte setting is off, we do not want to return the knownMethodData
- return use4ByteResolution ? knownMethodData?.[fourBytePrefix] : undefined;
+ return use4ByteResolution ? knownMethodData?.[fourBytePrefix] ?? {} : {};
}
export function getFeatureFlags(state) {
From 2d660df004141caffa0edd60499f480642d7d13e Mon Sep 17 00:00:00 2001
From: Daniel <80175477+dan437@users.noreply.github.com>
Date: Tue, 17 Sep 2024 16:09:33 +0200
Subject: [PATCH 27/43] fix: Allow to re-submit a cancelled swap if cancelled
via a HW wallet (#27210)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
This PR is a partial cherry pick of [this
one](https://github.com/MetaMask/metamask-extension/pull/26251) and
fixes an edge case for [this
PR](https://github.com/MetaMask/metamask-extension/pull/25742), where
when a swap was cancelled on a HW device, the submit button for swaps
was disabled. Now a user can resubmit cancelled swaps repeatedly.
It was already fixed
[here](https://github.com/MetaMask/metamask-extension/pull/26251) about
a month ago, but it's not in the v12.3.0 release. That's why this
partial cherry-pick is needed.
## **Manual testing steps**
1. Go to Swaps with a HW wallet on Ethereum Mainnet and Smart
Transactions enabled in Advanced Settings
2. Submit a swap, but cancel it on a HW device
3. You should see the quote overview page again and the `Swap` button
should be enabled
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
ui/ducks/swaps/swaps.js | 4 ++--
ui/pages/swaps/prepare-swap-page/review-quote.js | 10 ++++++----
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/ui/ducks/swaps/swaps.js b/ui/ducks/swaps/swaps.js
index 6032d46814ef..fab4e3288237 100644
--- a/ui/ducks/swaps/swaps.js
+++ b/ui/ducks/swaps/swaps.js
@@ -973,7 +973,6 @@ export const signAndSendSwapsSmartTransaction = ({
);
if (!fees) {
log.error('"fetchSwapsSmartTransactionFees" failed');
- dispatch(setSwapsSTXSubmitLoading(false));
dispatch(setCurrentSmartTransactionsError(StxErrorTypes.unavailable));
return;
}
@@ -1026,7 +1025,6 @@ export const signAndSendSwapsSmartTransaction = ({
);
}
history.push(SMART_TRANSACTION_STATUS_ROUTE);
- dispatch(setSwapsSTXSubmitLoading(false));
} catch (e) {
console.log('signAndSendSwapsSmartTransaction error', e);
const {
@@ -1036,6 +1034,8 @@ export const signAndSendSwapsSmartTransaction = ({
const errorObj = parseSmartTransactionsError(e.message);
dispatch(setCurrentSmartTransactionsError(errorObj?.error));
}
+ } finally {
+ dispatch(setSwapsSTXSubmitLoading(false));
}
};
};
diff --git a/ui/pages/swaps/prepare-swap-page/review-quote.js b/ui/pages/swaps/prepare-swap-page/review-quote.js
index 0dc3f89009cb..7713c871adc1 100644
--- a/ui/pages/swaps/prepare-swap-page/review-quote.js
+++ b/ui/pages/swaps/prepare-swap-page/review-quote.js
@@ -963,17 +963,19 @@ export default function ReviewQuote({ setReceiveToAmount }) {
}, [dispatch, trackViewQuotePageLoadedEvent, reviewSwapClickedTimestamp]);
useEffect(() => {
- // if smart transaction error is turned off, reset submit clicked boolean
if (
- !currentSmartTransactionsEnabled &&
- currentSmartTransactionsError &&
- submitClicked
+ (!currentSmartTransactionsEnabled &&
+ currentSmartTransactionsError &&
+ submitClicked) ||
+ (isSmartTransaction && !swapsSTXLoading && submitClicked)
) {
setSubmitClicked(false);
}
}, [
currentSmartTransactionsEnabled,
currentSmartTransactionsError,
+ isSmartTransaction,
+ swapsSTXLoading,
submitClicked,
]);
From 0713e461f2183b096b9f4e77d762a415483f7757 Mon Sep 17 00:00:00 2001
From: martahj
Date: Tue, 17 Sep 2024 13:56:31 -0500
Subject: [PATCH 28/43] STX Timer bug cherrypick 12.3 (#26935)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
This PR fixes an issue where the STX status screen for a swap was
showing a 0:00 for the timer. It is a cherrypick of
https://github.com/MetaMask/metamask-extension/pull/25779 into v12.3.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25779?quickstart=1)
## **Related issues**
Related to: https://github.com/MetaMask/metamask-extension/pull/25063/
## **Manual testing steps**
1. Make sure Smart Transactions is on (Settings > Advanced)
2. Do a Swap
3. Observe that timer is not 0:00 and is a reasonable number
## **Screenshots/Recordings**
### **Before**
https://github.com/MetaMask/metamask-extension/assets/139582705/26fe6167-614f-4771-b35b-10803bc23fc0
### **After**
https://github.com/MetaMask/metamask-extension/assets/139582705/d92b933d-1011-48b4-bf04-344f275d35db
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **Pre-merge reviewer checklist**
- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] 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: infiniteflower <139582705+infiniteflower@users.noreply.github.com>
---
app/scripts/controllers/swaps/index.ts | 4 +++-
app/scripts/controllers/swaps/swaps.test.ts | 1 +
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/app/scripts/controllers/swaps/index.ts b/app/scripts/controllers/swaps/index.ts
index cefcc37d0305..0b623068d8f3 100644
--- a/app/scripts/controllers/swaps/index.ts
+++ b/app/scripts/controllers/swaps/index.ts
@@ -937,6 +937,7 @@ export default class SwapsController extends BaseController<
stxBatchStatus: refreshRates.stxBatchStatus * 1000,
stxStatusDeadline: refreshRates.stxStatusDeadline,
stxMaxFeeMultiplier: parameters.stxMaxFeeMultiplier,
+ swapsStxStatusDeadline: parameters.stxStatusDeadline,
};
}
@@ -1063,6 +1064,7 @@ export default class SwapsController extends BaseController<
stxBatchStatus: number;
stxStatusDeadline: number;
stxMaxFeeMultiplier: number;
+ swapsStxStatusDeadline: number;
} | null = null;
try {
@@ -1085,7 +1087,7 @@ export default class SwapsController extends BaseController<
swapsNetworkConfig?.stxMaxFeeMultiplier ||
FALLBACK_SMART_TRANSACTIONS_MAX_FEE_MULTIPLIER;
_state.swapsState.swapsStxStatusDeadline =
- swapsNetworkConfig?.stxStatusDeadline ||
+ swapsNetworkConfig?.swapsStxStatusDeadline ||
FALLBACK_SMART_TRANSACTIONS_DEADLINE;
});
}
diff --git a/app/scripts/controllers/swaps/swaps.test.ts b/app/scripts/controllers/swaps/swaps.test.ts
index 8b2fbd22d032..b13b5dff40ca 100644
--- a/app/scripts/controllers/swaps/swaps.test.ts
+++ b/app/scripts/controllers/swaps/swaps.test.ts
@@ -1171,6 +1171,7 @@ describe('SwapsController', function () {
const swapsQuotePrefetchingRefreshTime = 0;
const swapsStxBatchStatusRefreshTime = 0;
const swapsStxGetTransactionsRefreshTime = 0;
+ const swapsStxStatusDeadline = 0;
swapsController.__test__updateState({
swapsState: {
...swapsController.state.swapsState,
From 63cf08bc4b83f1d2e9c86dcdb27e26e3397e2971 Mon Sep 17 00:00:00 2001
From: Prithpal Sooriya
Date: Wed, 18 Sep 2024 13:56:46 +0100
Subject: [PATCH 29/43] fix: [cherrypick][V12.3.0] patch
profile-sync-controller storage entry path hash (#27219)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Patches the underlying `@metamask/profile-sync-controller` to use the
original storage key path for notifications.
This was merged in develop here
https://github.com/MetaMask/metamask-extension/pull/27224
This fixes a critical issue where we were not using the same UserStorage
hashed entry. See release library changelog
https://github.com/MetaMask/core/blob/main/packages/profile-sync-controller/CHANGELOG.md#fixed
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27219?quickstart=1)
## **Related issues**
Fixes:
## **Manual testing steps**
Test notifications flow, are notifications still working
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
...sync-controller-npm-0.2.0-4d922a9e03.patch | 323 ++++++++++++++++++
.../metamask-notifications.ts | 4 +-
package.json | 2 +-
yarn.lock | 22 +-
4 files changed, 346 insertions(+), 5 deletions(-)
create mode 100644 .yarn/patches/@metamask-profile-sync-controller-npm-0.2.0-4d922a9e03.patch
diff --git a/.yarn/patches/@metamask-profile-sync-controller-npm-0.2.0-4d922a9e03.patch b/.yarn/patches/@metamask-profile-sync-controller-npm-0.2.0-4d922a9e03.patch
new file mode 100644
index 000000000000..540b61f79c57
--- /dev/null
+++ b/.yarn/patches/@metamask-profile-sync-controller-npm-0.2.0-4d922a9e03.patch
@@ -0,0 +1,323 @@
+diff --git a/dist/chunk-77LSWSGB.js b/dist/chunk-77LSWSGB.js
+index 7f29fc213985d9817d7d279ae494f6a27527ecf8..fbfb937f3579c610ea3d800e8a3953f995462595 100644
+--- a/dist/chunk-77LSWSGB.js
++++ b/dist/chunk-77LSWSGB.js
+@@ -1,23 +1,17 @@
+-"use strict";Object.defineProperty(exports, "__esModule", {value: true});
++"use strict";
++Object.defineProperty(exports, "__esModule", { value: true });
+
++var _chunkR2S3HIDNjs = require("./chunk-R2S3HIDN.js");
+
+-var _chunkR2S3HIDNjs = require('./chunk-R2S3HIDN.js');
++var _chunk3TE6M5TVjs = require("./chunk-3TE6M5TV.js");
+
++var _chunkSLHAVOTEjs = require("./chunk-SLHAVOTE.js");
+
+-var _chunk3TE6M5TVjs = require('./chunk-3TE6M5TV.js');
++var _chunkAK7OTIWAjs = require("./chunk-AK7OTIWA.js");
+
++var _chunkT3FNDVE3js = require("./chunk-T3FNDVE3.js");
+
+-var _chunkSLHAVOTEjs = require('./chunk-SLHAVOTE.js');
+-
+-
+-var _chunkAK7OTIWAjs = require('./chunk-AK7OTIWA.js');
+-
+-
+-
+-var _chunkT3FNDVE3js = require('./chunk-T3FNDVE3.js');
+-
+-
+-var _chunkIGY2S5BCjs = require('./chunk-IGY2S5BC.js');
++var _chunkIGY2S5BCjs = require("./chunk-IGY2S5BC.js");
+
+ // src/controllers/user-storage/index.ts
+ var user_storage_exports = {};
+@@ -26,7 +20,7 @@ _chunkIGY2S5BCjs.__export.call(void 0, user_storage_exports, {
+ Encryption: () => _chunkT3FNDVE3js.encryption_default,
+ Mocks: () => fixtures_exports,
+ createSHA256Hash: () => _chunkT3FNDVE3js.createSHA256Hash,
+- defaultState: () => _chunkR2S3HIDNjs.defaultState
++ defaultState: () => _chunkR2S3HIDNjs.defaultState,
+ });
+
+ // src/controllers/user-storage/__fixtures__/index.ts
+@@ -36,46 +30,52 @@ _chunkIGY2S5BCjs.__export.call(void 0, fixtures_exports, {
+ MOCK_STORAGE_DATA: () => MOCK_STORAGE_DATA,
+ MOCK_STORAGE_KEY: () => MOCK_STORAGE_KEY,
+ MOCK_STORAGE_KEY_SIGNATURE: () => MOCK_STORAGE_KEY_SIGNATURE,
+- MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT: () => MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,
++ MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT: () =>
++ MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,
+ getMockUserStorageGetResponse: () => getMockUserStorageGetResponse,
+- getMockUserStoragePutResponse: () => getMockUserStoragePutResponse
++ getMockUserStoragePutResponse: () => getMockUserStoragePutResponse,
+ });
+
+ // src/controllers/user-storage/__fixtures__/mockStorage.ts
+ var MOCK_STORAGE_KEY_SIGNATURE = "mockStorageKey";
+-var MOCK_STORAGE_KEY = _chunkT3FNDVE3js.createSHA256Hash.call(void 0, MOCK_STORAGE_KEY_SIGNATURE);
+-var MOCK_STORAGE_DATA = JSON.stringify({ hello: "world" });
+-var MOCK_ENCRYPTED_STORAGE_DATA = _chunkAK7OTIWAjs.encryption_default.encryptString(
+- MOCK_STORAGE_DATA,
+- MOCK_STORAGE_KEY
++var MOCK_STORAGE_KEY = _chunkT3FNDVE3js.createSHA256Hash.call(
++ void 0,
++ MOCK_STORAGE_KEY_SIGNATURE
+ );
++var MOCK_STORAGE_DATA = JSON.stringify({ hello: "world" });
++var MOCK_ENCRYPTED_STORAGE_DATA =
++ _chunkAK7OTIWAjs.encryption_default.encryptString(
++ MOCK_STORAGE_DATA,
++ MOCK_STORAGE_KEY
++ );
+
+ // src/controllers/user-storage/__fixtures__/mockResponses.ts
+-var MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT = `${_chunk3TE6M5TVjs.USER_STORAGE_ENDPOINT}${_chunkSLHAVOTEjs.createEntryPath.call(void 0,
+- "notifications.notificationSettings",
++var MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT = `${
++ _chunk3TE6M5TVjs.USER_STORAGE_ENDPOINT
++}${_chunkSLHAVOTEjs.createEntryPath.call(
++ void 0,
++ "notifications.notification_settings",
+ MOCK_STORAGE_KEY
+ )}`;
+ var MOCK_GET_USER_STORAGE_RESPONSE = {
+ HashedKey: "HASHED_KEY",
+- Data: MOCK_ENCRYPTED_STORAGE_DATA
++ Data: MOCK_ENCRYPTED_STORAGE_DATA,
+ };
+ var getMockUserStorageGetResponse = () => {
+ return {
+ url: MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,
+ requestMethod: "GET",
+- response: MOCK_GET_USER_STORAGE_RESPONSE
++ response: MOCK_GET_USER_STORAGE_RESPONSE,
+ };
+ };
+ var getMockUserStoragePutResponse = () => {
+ return {
+ url: MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,
+ requestMethod: "PUT",
+- response: null
++ response: null,
+ };
+ };
+
+-
+-
+-
+-exports.fixtures_exports = fixtures_exports; exports.user_storage_exports = user_storage_exports;
++exports.fixtures_exports = fixtures_exports;
++exports.user_storage_exports = user_storage_exports;
+ //# sourceMappingURL=chunk-77LSWSGB.js.map
+diff --git a/dist/chunk-77LSWSGB.js.map b/dist/chunk-77LSWSGB.js.map
+index dae9a343058b5d0c21707b57044e7329082cc969..c7d6a2d8c599ca4e090cb928af1b8394634e04d3 100644
+--- a/dist/chunk-77LSWSGB.js.map
++++ b/dist/chunk-77LSWSGB.js.map
+@@ -1 +1 @@
+-{"version":3,"sources":["../src/controllers/user-storage/index.ts","../src/controllers/user-storage/__fixtures__/index.ts","../src/controllers/user-storage/__fixtures__/mockStorage.ts","../src/controllers/user-storage/__fixtures__/mockResponses.ts"],"names":["encryption_default"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,6BAA6B;AACnC,IAAM,mBAAmB,iBAAiB,0BAA0B;AACpE,IAAM,oBAAoB,KAAK,UAAU,EAAE,OAAO,QAAQ,CAAC;AAC3D,IAAM,8BAA8BA,oBAAW;AAAA,EACpD;AAAA,EACA;AACF;;;ACGO,IAAM,2CAA2C,GAAG,qBAAqB,GAAG;AAAA,EACjF;AAAA,EACA;AACF,CAAC;AAED,IAAM,iCAAyD;AAAA,EAC7D,WAAW;AAAA,EACX,MAAM;AACR;AAEO,IAAM,gCAAgC,MAAM;AACjD,SAAO;AAAA,IACL,KAAK;AAAA,IACL,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AACF;AAEO,IAAM,gCAAgC,MAAM;AACjD,SAAO;AAAA,IACL,KAAK;AAAA,IACL,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AACF","sourcesContent":["import Controller from './UserStorageController';\n\nexport { Controller };\nexport * from './UserStorageController';\nexport * from './encryption';\nexport * as Mocks from './__fixtures__';\n","export * from './mockResponses';\nexport * from './mockStorage';\n","import encryption, { createSHA256Hash } from '../encryption';\n\nexport const MOCK_STORAGE_KEY_SIGNATURE = 'mockStorageKey';\nexport const MOCK_STORAGE_KEY = createSHA256Hash(MOCK_STORAGE_KEY_SIGNATURE);\nexport const MOCK_STORAGE_DATA = JSON.stringify({ hello: 'world' });\nexport const MOCK_ENCRYPTED_STORAGE_DATA = encryption.encryptString(\n MOCK_STORAGE_DATA,\n MOCK_STORAGE_KEY,\n);\n","import { createEntryPath } from '../schema';\nimport type { GetUserStorageResponse } from '../services';\nimport { USER_STORAGE_ENDPOINT } from '../services';\nimport { MOCK_ENCRYPTED_STORAGE_DATA, MOCK_STORAGE_KEY } from './mockStorage';\n\ntype MockResponse = {\n url: string;\n requestMethod: 'GET' | 'POST' | 'PUT';\n response: unknown;\n};\n\nexport const MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT = `${USER_STORAGE_ENDPOINT}${createEntryPath(\n 'notifications.notificationSettings',\n MOCK_STORAGE_KEY,\n)}`;\n\nconst MOCK_GET_USER_STORAGE_RESPONSE: GetUserStorageResponse = {\n HashedKey: 'HASHED_KEY',\n Data: MOCK_ENCRYPTED_STORAGE_DATA,\n};\n\nexport const getMockUserStorageGetResponse = () => {\n return {\n url: MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,\n requestMethod: 'GET',\n response: MOCK_GET_USER_STORAGE_RESPONSE,\n } satisfies MockResponse;\n};\n\nexport const getMockUserStoragePutResponse = () => {\n return {\n url: MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,\n requestMethod: 'PUT',\n response: null,\n } satisfies MockResponse;\n};\n"]}
+\ No newline at end of file
++{"version":3,"sources":["../src/controllers/user-storage/index.ts","../src/controllers/user-storage/__fixtures__/index.ts","../src/controllers/user-storage/__fixtures__/mockStorage.ts","../src/controllers/user-storage/__fixtures__/mockResponses.ts"],"names":["encryption_default"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,6BAA6B;AACnC,IAAM,mBAAmB,iBAAiB,0BAA0B;AACpE,IAAM,oBAAoB,KAAK,UAAU,EAAE,OAAO,QAAQ,CAAC;AAC3D,IAAM,8BAA8BA,oBAAW;AAAA,EACpD;AAAA,EACA;AACF;;;ACGO,IAAM,2CAA2C,GAAG,qBAAqB,GAAG;AAAA,EACjF;AAAA,EACA;AACF,CAAC;AAED,IAAM,iCAAyD;AAAA,EAC7D,WAAW;AAAA,EACX,MAAM;AACR;AAEO,IAAM,gCAAgC,MAAM;AACjD,SAAO;AAAA,IACL,KAAK;AAAA,IACL,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AACF;AAEO,IAAM,gCAAgC,MAAM;AACjD,SAAO;AAAA,IACL,KAAK;AAAA,IACL,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AACF","sourcesContent":["import Controller from './UserStorageController';\n\nexport { Controller };\nexport * from './UserStorageController';\nexport * from './encryption';\nexport * as Mocks from './__fixtures__';\n","export * from './mockResponses';\nexport * from './mockStorage';\n","import encryption, { createSHA256Hash } from '../encryption';\n\nexport const MOCK_STORAGE_KEY_SIGNATURE = 'mockStorageKey';\nexport const MOCK_STORAGE_KEY = createSHA256Hash(MOCK_STORAGE_KEY_SIGNATURE);\nexport const MOCK_STORAGE_DATA = JSON.stringify({ hello: 'world' });\nexport const MOCK_ENCRYPTED_STORAGE_DATA = encryption.encryptString(\n MOCK_STORAGE_DATA,\n MOCK_STORAGE_KEY,\n);\n","import { createEntryPath } from '../schema';\nimport type { GetUserStorageResponse } from '../services';\nimport { USER_STORAGE_ENDPOINT } from '../services';\nimport { MOCK_ENCRYPTED_STORAGE_DATA, MOCK_STORAGE_KEY } from './mockStorage';\n\ntype MockResponse = {\n url: string;\n requestMethod: 'GET' | 'POST' | 'PUT';\n response: unknown;\n};\n\nexport const MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT = `${USER_STORAGE_ENDPOINT}${createEntryPath(\n 'notifications.notification_settings',\n MOCK_STORAGE_KEY,\n)}`;\n\nconst MOCK_GET_USER_STORAGE_RESPONSE: GetUserStorageResponse = {\n HashedKey: 'HASHED_KEY',\n Data: MOCK_ENCRYPTED_STORAGE_DATA,\n};\n\nexport const getMockUserStorageGetResponse = () => {\n return {\n url: MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,\n requestMethod: 'GET',\n response: MOCK_GET_USER_STORAGE_RESPONSE,\n } satisfies MockResponse;\n};\n\nexport const getMockUserStoragePutResponse = () => {\n return {\n url: MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,\n requestMethod: 'PUT',\n response: null,\n } satisfies MockResponse;\n};\n"]}
+\ No newline at end of file
+diff --git a/dist/chunk-ILIZJQ6X.mjs b/dist/chunk-ILIZJQ6X.mjs
+index 75b92fcd4de183213c06ef83b119fcd085087064..9732ca708bd2939972cf39f03a18878254354aa2 100644
+--- a/dist/chunk-ILIZJQ6X.mjs
++++ b/dist/chunk-ILIZJQ6X.mjs
+@@ -1,10 +1,8 @@
+-import {
+- createSHA256Hash
+-} from "./chunk-K5UKU454.mjs";
++import { createSHA256Hash } from "./chunk-K5UKU454.mjs";
+
+ // src/controllers/user-storage/schema.ts
+ var USER_STORAGE_SCHEMA = {
+- notifications: ["notificationSettings"]
++ notifications: ["notification_settings"],
+ };
+ var getFeatureAndKeyFromPath = (path) => {
+ const pathRegex = /^\w+\.\w+$/u;
+@@ -32,9 +30,5 @@ function createEntryPath(path, storageKey) {
+ return `/${feature}/${hashedKey}`;
+ }
+
+-export {
+- USER_STORAGE_SCHEMA,
+- getFeatureAndKeyFromPath,
+- createEntryPath
+-};
++export { USER_STORAGE_SCHEMA, getFeatureAndKeyFromPath, createEntryPath };
+ //# sourceMappingURL=chunk-ILIZJQ6X.mjs.map
+diff --git a/dist/chunk-ILIZJQ6X.mjs.map b/dist/chunk-ILIZJQ6X.mjs.map
+index 5cfdb8f82d2f3c75b64e692bcff173a81d75af8f..2caaf734426228ae7e8e08b24ac8fe7c763a2edd 100644
+--- a/dist/chunk-ILIZJQ6X.mjs.map
++++ b/dist/chunk-ILIZJQ6X.mjs.map
+@@ -1 +1 @@
+-{"version":3,"sources":["../src/controllers/user-storage/schema.ts"],"sourcesContent":["import { createSHA256Hash } from './encryption';\n\n/**\n * The User Storage Endpoint requires a feature name and a namespace key.\n * Developers can provide additional features and keys by extending these types below.\n */\n\nexport const USER_STORAGE_SCHEMA = {\n notifications: ['notificationSettings'],\n} as const;\n\ntype UserStorageSchema = typeof USER_STORAGE_SCHEMA;\ntype UserStorageFeatures = keyof UserStorageSchema;\ntype UserStorageFeatureKeys =\n UserStorageSchema[Feature][number];\n\ntype UserStorageFeatureAndKey = {\n feature: UserStorageFeatures;\n key: UserStorageFeatureKeys;\n};\n\nexport type UserStoragePath = {\n [K in keyof UserStorageSchema]: `${K}.${UserStorageSchema[K][number]}`;\n}[keyof UserStorageSchema];\n\nexport const getFeatureAndKeyFromPath = (\n path: UserStoragePath,\n): UserStorageFeatureAndKey => {\n const pathRegex = /^\\w+\\.\\w+$/u;\n\n if (!pathRegex.test(path)) {\n throw new Error(\n `user-storage - path is not in the correct format. Correct format: 'feature.key'`,\n );\n }\n\n const [feature, key] = path.split('.') as [\n UserStorageFeatures,\n UserStorageFeatureKeys,\n ];\n\n if (!(feature in USER_STORAGE_SCHEMA)) {\n throw new Error(`user-storage - invalid feature provided: ${feature}`);\n }\n\n const validFeature = USER_STORAGE_SCHEMA[feature] as readonly string[];\n\n if (!validFeature.includes(key)) {\n const validKeys = USER_STORAGE_SCHEMA[feature].join(', ');\n\n throw new Error(\n `user-storage - invalid key provided for this feature: ${key}. Valid keys: ${validKeys}`,\n );\n }\n\n return { feature, key };\n};\n\n/**\n * Constructs a unique entry path for a user.\n * This can be done due to the uniqueness of the storage key (no users will share the same storage key).\n * The users entry is a unique hash that cannot be reversed.\n *\n * @param path - string in the form of `${feature}.${key}` that matches schema\n * @param storageKey - users storage key\n * @returns path to store entry\n */\nexport function createEntryPath(\n path: UserStoragePath,\n storageKey: string,\n): string {\n const { feature, key } = getFeatureAndKeyFromPath(path);\n const hashedKey = createSHA256Hash(key + storageKey);\n\n return `/${feature}/${hashedKey}`;\n}\n"],"mappings":";;;;;AAOO,IAAM,sBAAsB;AAAA,EACjC,eAAe,CAAC,sBAAsB;AACxC;AAgBO,IAAM,2BAA2B,CACtC,SAC6B;AAC7B,QAAM,YAAY;AAElB,MAAI,CAAC,UAAU,KAAK,IAAI,GAAG;AACzB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,CAAC,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG;AAKrC,MAAI,EAAE,WAAW,sBAAsB;AACrC,UAAM,IAAI,MAAM,4CAA4C,OAAO,EAAE;AAAA,EACvE;AAEA,QAAM,eAAe,oBAAoB,OAAO;AAEhD,MAAI,CAAC,aAAa,SAAS,GAAG,GAAG;AAC/B,UAAM,YAAY,oBAAoB,OAAO,EAAE,KAAK,IAAI;AAExD,UAAM,IAAI;AAAA,MACR,yDAAyD,GAAG,iBAAiB,SAAS;AAAA,IACxF;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,IAAI;AACxB;AAWO,SAAS,gBACd,MACA,YACQ;AACR,QAAM,EAAE,SAAS,IAAI,IAAI,yBAAyB,IAAI;AACtD,QAAM,YAAY,iBAAiB,MAAM,UAAU;AAEnD,SAAO,IAAI,OAAO,IAAI,SAAS;AACjC;","names":[]}
+\ No newline at end of file
++{"version":3,"sources":["../src/controllers/user-storage/schema.ts"],"sourcesContent":["import { createSHA256Hash } from './encryption';\n\n/**\n * The User Storage Endpoint requires a feature name and a namespace key.\n * Developers can provide additional features and keys by extending these types below.\n */\n\nexport const USER_STORAGE_SCHEMA = {\n notifications: ['notification_settings'],\n} as const;\n\ntype UserStorageSchema = typeof USER_STORAGE_SCHEMA;\ntype UserStorageFeatures = keyof UserStorageSchema;\ntype UserStorageFeatureKeys =\n UserStorageSchema[Feature][number];\n\ntype UserStorageFeatureAndKey = {\n feature: UserStorageFeatures;\n key: UserStorageFeatureKeys;\n};\n\nexport type UserStoragePath = {\n [K in keyof UserStorageSchema]: `${K}.${UserStorageSchema[K][number]}`;\n}[keyof UserStorageSchema];\n\nexport const getFeatureAndKeyFromPath = (\n path: UserStoragePath,\n): UserStorageFeatureAndKey => {\n const pathRegex = /^\\w+\\.\\w+$/u;\n\n if (!pathRegex.test(path)) {\n throw new Error(\n `user-storage - path is not in the correct format. Correct format: 'feature.key'`,\n );\n }\n\n const [feature, key] = path.split('.') as [\n UserStorageFeatures,\n UserStorageFeatureKeys,\n ];\n\n if (!(feature in USER_STORAGE_SCHEMA)) {\n throw new Error(`user-storage - invalid feature provided: ${feature}`);\n }\n\n const validFeature = USER_STORAGE_SCHEMA[feature] as readonly string[];\n\n if (!validFeature.includes(key)) {\n const validKeys = USER_STORAGE_SCHEMA[feature].join(', ');\n\n throw new Error(\n `user-storage - invalid key provided for this feature: ${key}. Valid keys: ${validKeys}`,\n );\n }\n\n return { feature, key };\n};\n\n/**\n * Constructs a unique entry path for a user.\n * This can be done due to the uniqueness of the storage key (no users will share the same storage key).\n * The users entry is a unique hash that cannot be reversed.\n *\n * @param path - string in the form of `${feature}.${key}` that matches schema\n * @param storageKey - users storage key\n * @returns path to store entry\n */\nexport function createEntryPath(\n path: UserStoragePath,\n storageKey: string,\n): string {\n const { feature, key } = getFeatureAndKeyFromPath(path);\n const hashedKey = createSHA256Hash(key + storageKey);\n\n return `/${feature}/${hashedKey}`;\n}\n"],"mappings":";;;;;AAOO,IAAM,sBAAsB;AAAA,EACjC,eAAe,CAAC,sBAAsB;AACxC;AAgBO,IAAM,2BAA2B,CACtC,SAC6B;AAC7B,QAAM,YAAY;AAElB,MAAI,CAAC,UAAU,KAAK,IAAI,GAAG;AACzB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,CAAC,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG;AAKrC,MAAI,EAAE,WAAW,sBAAsB;AACrC,UAAM,IAAI,MAAM,4CAA4C,OAAO,EAAE;AAAA,EACvE;AAEA,QAAM,eAAe,oBAAoB,OAAO;AAEhD,MAAI,CAAC,aAAa,SAAS,GAAG,GAAG;AAC/B,UAAM,YAAY,oBAAoB,OAAO,EAAE,KAAK,IAAI;AAExD,UAAM,IAAI;AAAA,MACR,yDAAyD,GAAG,iBAAiB,SAAS;AAAA,IACxF;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,IAAI;AACxB;AAWO,SAAS,gBACd,MACA,YACQ;AACR,QAAM,EAAE,SAAS,IAAI,IAAI,yBAAyB,IAAI;AACtD,QAAM,YAAY,iBAAiB,MAAM,UAAU;AAEnD,SAAO,IAAI,OAAO,IAAI,SAAS;AACjC;","names":[]}
+\ No newline at end of file
+diff --git a/dist/chunk-IQECLCH4.mjs b/dist/chunk-IQECLCH4.mjs
+index fbfb0670fd8dd1c15cf1d70809a59ac10435af23..e4a5b1a4728a4d2dad7c1d64048d2a869b84874c 100644
+--- a/dist/chunk-IQECLCH4.mjs
++++ b/dist/chunk-IQECLCH4.mjs
+@@ -1,23 +1,9 @@
+-import {
+- UserStorageController,
+- defaultState
+-} from "./chunk-LNSB4L7K.mjs";
+-import {
+- USER_STORAGE_ENDPOINT
+-} from "./chunk-FU7PSGFP.mjs";
+-import {
+- createEntryPath
+-} from "./chunk-ILIZJQ6X.mjs";
+-import {
+- encryption_default as encryption_default2
+-} from "./chunk-5TOWF6UW.mjs";
+-import {
+- createSHA256Hash,
+- encryption_default
+-} from "./chunk-K5UKU454.mjs";
+-import {
+- __export
+-} from "./chunk-U5UIDVOO.mjs";
++import { UserStorageController, defaultState } from "./chunk-LNSB4L7K.mjs";
++import { USER_STORAGE_ENDPOINT } from "./chunk-FU7PSGFP.mjs";
++import { createEntryPath } from "./chunk-ILIZJQ6X.mjs";
++import { encryption_default as encryption_default2 } from "./chunk-5TOWF6UW.mjs";
++import { createSHA256Hash, encryption_default } from "./chunk-K5UKU454.mjs";
++import { __export } from "./chunk-U5UIDVOO.mjs";
+
+ // src/controllers/user-storage/index.ts
+ var user_storage_exports = {};
+@@ -26,7 +12,7 @@ __export(user_storage_exports, {
+ Encryption: () => encryption_default,
+ Mocks: () => fixtures_exports,
+ createSHA256Hash: () => createSHA256Hash,
+- defaultState: () => defaultState
++ defaultState: () => defaultState,
+ });
+
+ // src/controllers/user-storage/__fixtures__/index.ts
+@@ -36,9 +22,10 @@ __export(fixtures_exports, {
+ MOCK_STORAGE_DATA: () => MOCK_STORAGE_DATA,
+ MOCK_STORAGE_KEY: () => MOCK_STORAGE_KEY,
+ MOCK_STORAGE_KEY_SIGNATURE: () => MOCK_STORAGE_KEY_SIGNATURE,
+- MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT: () => MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,
++ MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT: () =>
++ MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,
+ getMockUserStorageGetResponse: () => getMockUserStorageGetResponse,
+- getMockUserStoragePutResponse: () => getMockUserStoragePutResponse
++ getMockUserStoragePutResponse: () => getMockUserStoragePutResponse,
+ });
+
+ // src/controllers/user-storage/__fixtures__/mockStorage.ts
+@@ -52,30 +39,27 @@ var MOCK_ENCRYPTED_STORAGE_DATA = encryption_default2.encryptString(
+
+ // src/controllers/user-storage/__fixtures__/mockResponses.ts
+ var MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT = `${USER_STORAGE_ENDPOINT}${createEntryPath(
+- "notifications.notificationSettings",
++ "notifications.notification_settings",
+ MOCK_STORAGE_KEY
+ )}`;
+ var MOCK_GET_USER_STORAGE_RESPONSE = {
+ HashedKey: "HASHED_KEY",
+- Data: MOCK_ENCRYPTED_STORAGE_DATA
++ Data: MOCK_ENCRYPTED_STORAGE_DATA,
+ };
+ var getMockUserStorageGetResponse = () => {
+ return {
+ url: MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,
+ requestMethod: "GET",
+- response: MOCK_GET_USER_STORAGE_RESPONSE
++ response: MOCK_GET_USER_STORAGE_RESPONSE,
+ };
+ };
+ var getMockUserStoragePutResponse = () => {
+ return {
+ url: MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,
+ requestMethod: "PUT",
+- response: null
++ response: null,
+ };
+ };
+
+-export {
+- fixtures_exports,
+- user_storage_exports
+-};
++export { fixtures_exports, user_storage_exports };
+ //# sourceMappingURL=chunk-IQECLCH4.mjs.map
+diff --git a/dist/chunk-IQECLCH4.mjs.map b/dist/chunk-IQECLCH4.mjs.map
+index 431f888e4c0a529b7213d83381f50ad5657899f9..78bc07ced21dbad3da0a955cb0d0d9a49ac53cb6 100644
+--- a/dist/chunk-IQECLCH4.mjs.map
++++ b/dist/chunk-IQECLCH4.mjs.map
+@@ -1 +1 @@
+-{"version":3,"sources":["../src/controllers/user-storage/index.ts","../src/controllers/user-storage/__fixtures__/index.ts","../src/controllers/user-storage/__fixtures__/mockStorage.ts","../src/controllers/user-storage/__fixtures__/mockResponses.ts"],"sourcesContent":["import Controller from './UserStorageController';\n\nexport { Controller };\nexport * from './UserStorageController';\nexport * from './encryption';\nexport * as Mocks from './__fixtures__';\n","export * from './mockResponses';\nexport * from './mockStorage';\n","import encryption, { createSHA256Hash } from '../encryption';\n\nexport const MOCK_STORAGE_KEY_SIGNATURE = 'mockStorageKey';\nexport const MOCK_STORAGE_KEY = createSHA256Hash(MOCK_STORAGE_KEY_SIGNATURE);\nexport const MOCK_STORAGE_DATA = JSON.stringify({ hello: 'world' });\nexport const MOCK_ENCRYPTED_STORAGE_DATA = encryption.encryptString(\n MOCK_STORAGE_DATA,\n MOCK_STORAGE_KEY,\n);\n","import { createEntryPath } from '../schema';\nimport type { GetUserStorageResponse } from '../services';\nimport { USER_STORAGE_ENDPOINT } from '../services';\nimport { MOCK_ENCRYPTED_STORAGE_DATA, MOCK_STORAGE_KEY } from './mockStorage';\n\ntype MockResponse = {\n url: string;\n requestMethod: 'GET' | 'POST' | 'PUT';\n response: unknown;\n};\n\nexport const MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT = `${USER_STORAGE_ENDPOINT}${createEntryPath(\n 'notifications.notificationSettings',\n MOCK_STORAGE_KEY,\n)}`;\n\nconst MOCK_GET_USER_STORAGE_RESPONSE: GetUserStorageResponse = {\n HashedKey: 'HASHED_KEY',\n Data: MOCK_ENCRYPTED_STORAGE_DATA,\n};\n\nexport const getMockUserStorageGetResponse = () => {\n return {\n url: MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,\n requestMethod: 'GET',\n response: MOCK_GET_USER_STORAGE_RESPONSE,\n } satisfies MockResponse;\n};\n\nexport const getMockUserStoragePutResponse = () => {\n return {\n url: MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,\n requestMethod: 'PUT',\n response: null,\n } satisfies MockResponse;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,6BAA6B;AACnC,IAAM,mBAAmB,iBAAiB,0BAA0B;AACpE,IAAM,oBAAoB,KAAK,UAAU,EAAE,OAAO,QAAQ,CAAC;AAC3D,IAAM,8BAA8BA,oBAAW;AAAA,EACpD;AAAA,EACA;AACF;;;ACGO,IAAM,2CAA2C,GAAG,qBAAqB,GAAG;AAAA,EACjF;AAAA,EACA;AACF,CAAC;AAED,IAAM,iCAAyD;AAAA,EAC7D,WAAW;AAAA,EACX,MAAM;AACR;AAEO,IAAM,gCAAgC,MAAM;AACjD,SAAO;AAAA,IACL,KAAK;AAAA,IACL,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AACF;AAEO,IAAM,gCAAgC,MAAM;AACjD,SAAO;AAAA,IACL,KAAK;AAAA,IACL,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AACF;","names":["encryption_default"]}
+\ No newline at end of file
++{"version":3,"sources":["../src/controllers/user-storage/index.ts","../src/controllers/user-storage/__fixtures__/index.ts","../src/controllers/user-storage/__fixtures__/mockStorage.ts","../src/controllers/user-storage/__fixtures__/mockResponses.ts"],"sourcesContent":["import Controller from './UserStorageController';\n\nexport { Controller };\nexport * from './UserStorageController';\nexport * from './encryption';\nexport * as Mocks from './__fixtures__';\n","export * from './mockResponses';\nexport * from './mockStorage';\n","import encryption, { createSHA256Hash } from '../encryption';\n\nexport const MOCK_STORAGE_KEY_SIGNATURE = 'mockStorageKey';\nexport const MOCK_STORAGE_KEY = createSHA256Hash(MOCK_STORAGE_KEY_SIGNATURE);\nexport const MOCK_STORAGE_DATA = JSON.stringify({ hello: 'world' });\nexport const MOCK_ENCRYPTED_STORAGE_DATA = encryption.encryptString(\n MOCK_STORAGE_DATA,\n MOCK_STORAGE_KEY,\n);\n","import { createEntryPath } from '../schema';\nimport type { GetUserStorageResponse } from '../services';\nimport { USER_STORAGE_ENDPOINT } from '../services';\nimport { MOCK_ENCRYPTED_STORAGE_DATA, MOCK_STORAGE_KEY } from './mockStorage';\n\ntype MockResponse = {\n url: string;\n requestMethod: 'GET' | 'POST' | 'PUT';\n response: unknown;\n};\n\nexport const MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT = `${USER_STORAGE_ENDPOINT}${createEntryPath(\n 'notifications.notification_settings',\n MOCK_STORAGE_KEY,\n)}`;\n\nconst MOCK_GET_USER_STORAGE_RESPONSE: GetUserStorageResponse = {\n HashedKey: 'HASHED_KEY',\n Data: MOCK_ENCRYPTED_STORAGE_DATA,\n};\n\nexport const getMockUserStorageGetResponse = () => {\n return {\n url: MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,\n requestMethod: 'GET',\n response: MOCK_GET_USER_STORAGE_RESPONSE,\n } satisfies MockResponse;\n};\n\nexport const getMockUserStoragePutResponse = () => {\n return {\n url: MOCK_USER_STORAGE_NOTIFICATIONS_ENDPOINT,\n requestMethod: 'PUT',\n response: null,\n } satisfies MockResponse;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,6BAA6B;AACnC,IAAM,mBAAmB,iBAAiB,0BAA0B;AACpE,IAAM,oBAAoB,KAAK,UAAU,EAAE,OAAO,QAAQ,CAAC;AAC3D,IAAM,8BAA8BA,oBAAW;AAAA,EACpD;AAAA,EACA;AACF;;;ACGO,IAAM,2CAA2C,GAAG,qBAAqB,GAAG;AAAA,EACjF;AAAA,EACA;AACF,CAAC;AAED,IAAM,iCAAyD;AAAA,EAC7D,WAAW;AAAA,EACX,MAAM;AACR;AAEO,IAAM,gCAAgC,MAAM;AACjD,SAAO;AAAA,IACL,KAAK;AAAA,IACL,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AACF;AAEO,IAAM,gCAAgC,MAAM;AACjD,SAAO;AAAA,IACL,KAAK;AAAA,IACL,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AACF;","names":["encryption_default"]}
+\ No newline at end of file
+diff --git a/dist/chunk-SLHAVOTE.js b/dist/chunk-SLHAVOTE.js
+index 74a4398618d0d0f6a9a6b57b299722df40ced840..f4765cb6110283c23a87685665a980faaaa84152 100644
+--- a/dist/chunk-SLHAVOTE.js
++++ b/dist/chunk-SLHAVOTE.js
+@@ -1,10 +1,11 @@
+-"use strict";Object.defineProperty(exports, "__esModule", {value: true});
++"use strict";
++Object.defineProperty(exports, "__esModule", { value: true });
+
+-var _chunkT3FNDVE3js = require('./chunk-T3FNDVE3.js');
++var _chunkT3FNDVE3js = require("./chunk-T3FNDVE3.js");
+
+ // src/controllers/user-storage/schema.ts
+ var USER_STORAGE_SCHEMA = {
+- notifications: ["notificationSettings"]
++ notifications: ["notification_settings"],
+ };
+ var getFeatureAndKeyFromPath = (path) => {
+ const pathRegex = /^\w+\.\w+$/u;
+@@ -28,13 +29,14 @@ var getFeatureAndKeyFromPath = (path) => {
+ };
+ function createEntryPath(path, storageKey) {
+ const { feature, key } = getFeatureAndKeyFromPath(path);
+- const hashedKey = _chunkT3FNDVE3js.createSHA256Hash.call(void 0, key + storageKey);
++ const hashedKey = _chunkT3FNDVE3js.createSHA256Hash.call(
++ void 0,
++ key + storageKey
++ );
+ return `/${feature}/${hashedKey}`;
+ }
+
+-
+-
+-
+-
+-exports.USER_STORAGE_SCHEMA = USER_STORAGE_SCHEMA; exports.getFeatureAndKeyFromPath = getFeatureAndKeyFromPath; exports.createEntryPath = createEntryPath;
++exports.USER_STORAGE_SCHEMA = USER_STORAGE_SCHEMA;
++exports.getFeatureAndKeyFromPath = getFeatureAndKeyFromPath;
++exports.createEntryPath = createEntryPath;
+ //# sourceMappingURL=chunk-SLHAVOTE.js.map
+diff --git a/dist/chunk-SLHAVOTE.js.map b/dist/chunk-SLHAVOTE.js.map
+index 9c00f76f521bd1783bf4dc24300cc51b412761c8..ed723ce11446984f3db8cb9c41b42a592c57398e 100644
+--- a/dist/chunk-SLHAVOTE.js.map
++++ b/dist/chunk-SLHAVOTE.js.map
+@@ -1 +1 @@
+-{"version":3,"sources":["../src/controllers/user-storage/schema.ts"],"names":[],"mappings":";;;;;AAOO,IAAM,sBAAsB;AAAA,EACjC,eAAe,CAAC,sBAAsB;AACxC;AAgBO,IAAM,2BAA2B,CACtC,SAC6B;AAC7B,QAAM,YAAY;AAElB,MAAI,CAAC,UAAU,KAAK,IAAI,GAAG;AACzB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,CAAC,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG;AAKrC,MAAI,EAAE,WAAW,sBAAsB;AACrC,UAAM,IAAI,MAAM,4CAA4C,OAAO,EAAE;AAAA,EACvE;AAEA,QAAM,eAAe,oBAAoB,OAAO;AAEhD,MAAI,CAAC,aAAa,SAAS,GAAG,GAAG;AAC/B,UAAM,YAAY,oBAAoB,OAAO,EAAE,KAAK,IAAI;AAExD,UAAM,IAAI;AAAA,MACR,yDAAyD,GAAG,iBAAiB,SAAS;AAAA,IACxF;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,IAAI;AACxB;AAWO,SAAS,gBACd,MACA,YACQ;AACR,QAAM,EAAE,SAAS,IAAI,IAAI,yBAAyB,IAAI;AACtD,QAAM,YAAY,iBAAiB,MAAM,UAAU;AAEnD,SAAO,IAAI,OAAO,IAAI,SAAS;AACjC","sourcesContent":["import { createSHA256Hash } from './encryption';\n\n/**\n * The User Storage Endpoint requires a feature name and a namespace key.\n * Developers can provide additional features and keys by extending these types below.\n */\n\nexport const USER_STORAGE_SCHEMA = {\n notifications: ['notificationSettings'],\n} as const;\n\ntype UserStorageSchema = typeof USER_STORAGE_SCHEMA;\ntype UserStorageFeatures = keyof UserStorageSchema;\ntype UserStorageFeatureKeys =\n UserStorageSchema[Feature][number];\n\ntype UserStorageFeatureAndKey = {\n feature: UserStorageFeatures;\n key: UserStorageFeatureKeys;\n};\n\nexport type UserStoragePath = {\n [K in keyof UserStorageSchema]: `${K}.${UserStorageSchema[K][number]}`;\n}[keyof UserStorageSchema];\n\nexport const getFeatureAndKeyFromPath = (\n path: UserStoragePath,\n): UserStorageFeatureAndKey => {\n const pathRegex = /^\\w+\\.\\w+$/u;\n\n if (!pathRegex.test(path)) {\n throw new Error(\n `user-storage - path is not in the correct format. Correct format: 'feature.key'`,\n );\n }\n\n const [feature, key] = path.split('.') as [\n UserStorageFeatures,\n UserStorageFeatureKeys,\n ];\n\n if (!(feature in USER_STORAGE_SCHEMA)) {\n throw new Error(`user-storage - invalid feature provided: ${feature}`);\n }\n\n const validFeature = USER_STORAGE_SCHEMA[feature] as readonly string[];\n\n if (!validFeature.includes(key)) {\n const validKeys = USER_STORAGE_SCHEMA[feature].join(', ');\n\n throw new Error(\n `user-storage - invalid key provided for this feature: ${key}. Valid keys: ${validKeys}`,\n );\n }\n\n return { feature, key };\n};\n\n/**\n * Constructs a unique entry path for a user.\n * This can be done due to the uniqueness of the storage key (no users will share the same storage key).\n * The users entry is a unique hash that cannot be reversed.\n *\n * @param path - string in the form of `${feature}.${key}` that matches schema\n * @param storageKey - users storage key\n * @returns path to store entry\n */\nexport function createEntryPath(\n path: UserStoragePath,\n storageKey: string,\n): string {\n const { feature, key } = getFeatureAndKeyFromPath(path);\n const hashedKey = createSHA256Hash(key + storageKey);\n\n return `/${feature}/${hashedKey}`;\n}\n"]}
+\ No newline at end of file
++{"version":3,"sources":["../src/controllers/user-storage/schema.ts"],"names":[],"mappings":";;;;;AAOO,IAAM,sBAAsB;AAAA,EACjC,eAAe,CAAC,sBAAsB;AACxC;AAgBO,IAAM,2BAA2B,CACtC,SAC6B;AAC7B,QAAM,YAAY;AAElB,MAAI,CAAC,UAAU,KAAK,IAAI,GAAG;AACzB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,CAAC,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG;AAKrC,MAAI,EAAE,WAAW,sBAAsB;AACrC,UAAM,IAAI,MAAM,4CAA4C,OAAO,EAAE;AAAA,EACvE;AAEA,QAAM,eAAe,oBAAoB,OAAO;AAEhD,MAAI,CAAC,aAAa,SAAS,GAAG,GAAG;AAC/B,UAAM,YAAY,oBAAoB,OAAO,EAAE,KAAK,IAAI;AAExD,UAAM,IAAI;AAAA,MACR,yDAAyD,GAAG,iBAAiB,SAAS;AAAA,IACxF;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,IAAI;AACxB;AAWO,SAAS,gBACd,MACA,YACQ;AACR,QAAM,EAAE,SAAS,IAAI,IAAI,yBAAyB,IAAI;AACtD,QAAM,YAAY,iBAAiB,MAAM,UAAU;AAEnD,SAAO,IAAI,OAAO,IAAI,SAAS;AACjC","sourcesContent":["import { createSHA256Hash } from './encryption';\n\n/**\n * The User Storage Endpoint requires a feature name and a namespace key.\n * Developers can provide additional features and keys by extending these types below.\n */\n\nexport const USER_STORAGE_SCHEMA = {\n notifications: ['notification_settings'],\n} as const;\n\ntype UserStorageSchema = typeof USER_STORAGE_SCHEMA;\ntype UserStorageFeatures = keyof UserStorageSchema;\ntype UserStorageFeatureKeys =\n UserStorageSchema[Feature][number];\n\ntype UserStorageFeatureAndKey = {\n feature: UserStorageFeatures;\n key: UserStorageFeatureKeys;\n};\n\nexport type UserStoragePath = {\n [K in keyof UserStorageSchema]: `${K}.${UserStorageSchema[K][number]}`;\n}[keyof UserStorageSchema];\n\nexport const getFeatureAndKeyFromPath = (\n path: UserStoragePath,\n): UserStorageFeatureAndKey => {\n const pathRegex = /^\\w+\\.\\w+$/u;\n\n if (!pathRegex.test(path)) {\n throw new Error(\n `user-storage - path is not in the correct format. Correct format: 'feature.key'`,\n );\n }\n\n const [feature, key] = path.split('.') as [\n UserStorageFeatures,\n UserStorageFeatureKeys,\n ];\n\n if (!(feature in USER_STORAGE_SCHEMA)) {\n throw new Error(`user-storage - invalid feature provided: ${feature}`);\n }\n\n const validFeature = USER_STORAGE_SCHEMA[feature] as readonly string[];\n\n if (!validFeature.includes(key)) {\n const validKeys = USER_STORAGE_SCHEMA[feature].join(', ');\n\n throw new Error(\n `user-storage - invalid key provided for this feature: ${key}. Valid keys: ${validKeys}`,\n );\n }\n\n return { feature, key };\n};\n\n/**\n * Constructs a unique entry path for a user.\n * This can be done due to the uniqueness of the storage key (no users will share the same storage key).\n * The users entry is a unique hash that cannot be reversed.\n *\n * @param path - string in the form of `${feature}.${key}` that matches schema\n * @param storageKey - users storage key\n * @returns path to store entry\n */\nexport function createEntryPath(\n path: UserStoragePath,\n storageKey: string,\n): string {\n const { feature, key } = getFeatureAndKeyFromPath(path);\n const hashedKey = createSHA256Hash(key + storageKey);\n\n return `/${feature}/${hashedKey}`;\n}\n"]}
+\ No newline at end of file
+diff --git a/dist/types/controllers/user-storage/schema.d.ts b/dist/types/controllers/user-storage/schema.d.ts
+index 0f7fa2b3224fcafc1e01869338a9b978a50a2b4e..311b0309b076dd1d0d05e59ff20845952bc917d9 100644
+--- a/dist/types/controllers/user-storage/schema.d.ts
++++ b/dist/types/controllers/user-storage/schema.d.ts
+@@ -3,7 +3,7 @@
+ * Developers can provide additional features and keys by extending these types below.
+ */
+ export declare const USER_STORAGE_SCHEMA: {
+- readonly notifications: readonly ["notificationSettings"];
++ readonly notifications: readonly ["notification_settings"];
+ };
+ type UserStorageSchema = typeof USER_STORAGE_SCHEMA;
+ type UserStorageFeatures = keyof UserStorageSchema;
diff --git a/app/scripts/controllers/metamask-notifications/metamask-notifications.ts b/app/scripts/controllers/metamask-notifications/metamask-notifications.ts
index 65b4aed86b37..a2fba0fe3cef 100644
--- a/app/scripts/controllers/metamask-notifications/metamask-notifications.ts
+++ b/app/scripts/controllers/metamask-notifications/metamask-notifications.ts
@@ -289,13 +289,13 @@ export class MetamaskNotificationsController extends BaseController<
getNotificationStorage: async () => {
return await this.messagingSystem.call(
'UserStorageController:performGetStorage',
- 'notifications.notificationSettings',
+ 'notifications.notification_settings',
);
},
setNotificationStorage: async (state: string) => {
return await this.messagingSystem.call(
'UserStorageController:performSetStorage',
- 'notifications.notificationSettings',
+ 'notifications.notification_settings',
state,
);
},
diff --git a/package.json b/package.json
index 29c066a67d57..40b383e90794 100644
--- a/package.json
+++ b/package.json
@@ -341,7 +341,7 @@
"@metamask/phishing-controller": "^9.0.3",
"@metamask/post-message-stream": "^8.0.0",
"@metamask/ppom-validator": "^0.32.0",
- "@metamask/profile-sync-controller": "^0.2.0",
+ "@metamask/profile-sync-controller": "patch:@metamask/profile-sync-controller@npm%3A0.2.0#~/.yarn/patches/@metamask-profile-sync-controller-npm-0.2.0-4d922a9e03.patch",
"@metamask/providers": "^14.0.2",
"@metamask/queued-request-controller": "^2.0.0",
"@metamask/rate-limit-controller": "^5.0.1",
diff --git a/yarn.lock b/yarn.lock
index 7bbc4c2a1cd3..d0a172e1d380 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6069,7 +6069,7 @@ __metadata:
languageName: node
linkType: hard
-"@metamask/profile-sync-controller@npm:^0.2.0":
+"@metamask/profile-sync-controller@npm:0.2.0":
version: 0.2.0
resolution: "@metamask/profile-sync-controller@npm:0.2.0"
dependencies:
@@ -6087,6 +6087,24 @@ __metadata:
languageName: node
linkType: hard
+"@metamask/profile-sync-controller@patch:@metamask/profile-sync-controller@npm%3A0.2.0#~/.yarn/patches/@metamask-profile-sync-controller-npm-0.2.0-4d922a9e03.patch":
+ version: 0.2.0
+ resolution: "@metamask/profile-sync-controller@patch:@metamask/profile-sync-controller@npm%3A0.2.0#~/.yarn/patches/@metamask-profile-sync-controller-npm-0.2.0-4d922a9e03.patch::version=0.2.0&hash=7a9e6a"
+ dependencies:
+ "@metamask/base-controller": "npm:^6.0.2"
+ "@metamask/snaps-sdk": "npm:^6.1.1"
+ "@metamask/snaps-utils": "npm:^7.8.1"
+ "@noble/ciphers": "npm:^0.5.2"
+ "@noble/hashes": "npm:^1.4.0"
+ immer: "npm:^9.0.6"
+ loglevel: "npm:^1.8.1"
+ siwe: "npm:^2.3.2"
+ peerDependencies:
+ "@metamask/snaps-controllers": ^9.3.0
+ checksum: 10/58a6ab0b93e47379c4b6c529f06dd1b59f0b7fe1695639823e8dadad6ecd5015db93c07196fb76f08db5df4b4d33133da07db3a9ced542e69d1568041b0da19d
+ languageName: node
+ linkType: hard
+
"@metamask/providers@npm:^14.0.2":
version: 14.0.2
resolution: "@metamask/providers@npm:14.0.2"
@@ -25964,7 +25982,7 @@ __metadata:
"@metamask/phishing-warning": "npm:^3.0.3"
"@metamask/post-message-stream": "npm:^8.0.0"
"@metamask/ppom-validator": "npm:^0.32.0"
- "@metamask/profile-sync-controller": "npm:^0.2.0"
+ "@metamask/profile-sync-controller": "patch:@metamask/profile-sync-controller@npm%3A0.2.0#~/.yarn/patches/@metamask-profile-sync-controller-npm-0.2.0-4d922a9e03.patch"
"@metamask/providers": "npm:^14.0.2"
"@metamask/queued-request-controller": "npm:^2.0.0"
"@metamask/rate-limit-controller": "npm:^5.0.1"
From 3373b9a1df2f8e62b39b6cbd233ace00fc4d2c68 Mon Sep 17 00:00:00 2001
From: Niranjana Binoy <43930900+NiranjanaBinoy@users.noreply.github.com>
Date: Wed, 18 Sep 2024 09:30:40 -0400
Subject: [PATCH 30/43] fix(cherry-pick): Adding "cookie id" to metrics event
(#26697) (#27227)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Cherry picking #26697 to V12.3.0
#26697 sets up a stream communication with the label
'metamask-cookie-handler'. The data sent from the page will be
intercepted at the content-script and forwarded to the extension. The
'ga_client_id' sent from the page is saved as
`marketingCampaignCookieId` in the metaMetricsController state and
fetched when building the context for each event.
## **Description**
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27227?quickstart=1)
## **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 Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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/scripts/background.js | 18 +-
.../constants/marketing-site-whitelist.ts | 15 ++
app/scripts/constants/sentry-state.ts | 1 +
app/scripts/constants/stream.ts | 17 ++
app/scripts/contentscript.js | 55 ++++-
app/scripts/controllers/metametrics.js | 14 ++
app/scripts/controllers/metametrics.test.js | 82 ++++++-
app/scripts/metamask-controller.js | 41 ++++
app/scripts/streams/cookie-handler-stream.ts | 193 +++++++++++++++
app/scripts/streams/shared.ts | 15 ++
.../marketing-cookieid-mock-page/index.html | 35 +++
.../tests/metrics/marketing-cookieid.spec.ts | 231 ++++++++++++++++++
...rs-after-init-opt-in-background-state.json | 1 +
.../errors-after-init-opt-in-ui-state.json | 1 +
14 files changed, 703 insertions(+), 16 deletions(-)
create mode 100644 app/scripts/constants/marketing-site-whitelist.ts
create mode 100644 app/scripts/constants/stream.ts
create mode 100644 app/scripts/streams/cookie-handler-stream.ts
create mode 100644 app/scripts/streams/shared.ts
create mode 100644 test/e2e/tests/metrics/marketing-cookieid-mock-page/index.html
create mode 100644 test/e2e/tests/metrics/marketing-cookieid.spec.ts
diff --git a/app/scripts/background.js b/app/scripts/background.js
index b369cd18ed0b..11a0b059a25f 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -80,6 +80,7 @@ import { createOffscreen } from './offscreen';
/* eslint-enable import/first */
import { TRIGGER_TYPES } from './controllers/metamask-notifications/constants/notification-schema';
+import { COOKIE_ID_MARKETING_WHITELIST_ORIGINS } from './constants/marketing-site-whitelist';
// eslint-disable-next-line @metamask/design-tokens/color-no-hex
const BADGE_COLOR_APPROVAL = '#0376C9';
@@ -123,6 +124,7 @@ if (inTest || process.env.METAMASK_DEBUG) {
}
const phishingPageUrl = new URL(process.env.PHISHING_WARNING_PAGE_URL);
+
// normalized (adds a trailing slash to the end of the domain if it's missing)
// the URL once and reuse it:
const phishingPageHref = phishingPageUrl.toString();
@@ -865,10 +867,10 @@ export function setupController(
senderUrl.origin === phishingPageUrl.origin &&
senderUrl.pathname === phishingPageUrl.pathname
) {
- const portStream =
+ const portStreamForPhishingPage =
overrides?.getPortStream?.(remotePort) || new PortStream(remotePort);
controller.setupPhishingCommunication({
- connectionStream: portStream,
+ connectionStream: portStreamForPhishingPage,
});
} else {
// this is triggered when a new tab is opened, or origin(url) is changed
@@ -888,6 +890,18 @@ export function setupController(
}
});
}
+ if (
+ senderUrl &&
+ COOKIE_ID_MARKETING_WHITELIST_ORIGINS.some(
+ (origin) => origin === senderUrl.origin,
+ )
+ ) {
+ const portStreamForCookieHandlerPage =
+ overrides?.getPortStream?.(remotePort) || new PortStream(remotePort);
+ controller.setUpCookieHandlerCommunication({
+ connectionStream: portStreamForCookieHandlerPage,
+ });
+ }
connectExternalExtension(remotePort);
}
};
diff --git a/app/scripts/constants/marketing-site-whitelist.ts b/app/scripts/constants/marketing-site-whitelist.ts
new file mode 100644
index 000000000000..8ff0cfd2de78
--- /dev/null
+++ b/app/scripts/constants/marketing-site-whitelist.ts
@@ -0,0 +1,15 @@
+export const COOKIE_ID_MARKETING_WHITELIST = [
+ 'https://metamask.io',
+ 'https://learn.metamask.io',
+ 'https://mmi-support.zendesk.com',
+ 'https://community.metamask.io',
+ 'https://support.metamask.io',
+];
+
+if (process.env.IN_TEST) {
+ COOKIE_ID_MARKETING_WHITELIST.push('http://127.0.0.1:8080');
+}
+
+// Extract the origin of each URL in the whitelist
+export const COOKIE_ID_MARKETING_WHITELIST_ORIGINS =
+ COOKIE_ID_MARKETING_WHITELIST.map((url) => new URL(url).origin);
diff --git a/app/scripts/constants/sentry-state.ts b/app/scripts/constants/sentry-state.ts
index b275dfcb7a8f..ae00352b4e72 100644
--- a/app/scripts/constants/sentry-state.ts
+++ b/app/scripts/constants/sentry-state.ts
@@ -156,6 +156,7 @@ export const SENTRY_BACKGROUND_STATE = {
segmentApiCalls: false,
traits: false,
dataCollectionForMarketing: false,
+ marketingCampaignCookieId: true,
},
NameController: {
names: false,
diff --git a/app/scripts/constants/stream.ts b/app/scripts/constants/stream.ts
new file mode 100644
index 000000000000..8552b49357dd
--- /dev/null
+++ b/app/scripts/constants/stream.ts
@@ -0,0 +1,17 @@
+// contexts
+export const CONTENT_SCRIPT = 'metamask-contentscript';
+export const METAMASK_INPAGE = 'metamask-inpage';
+
+// stream channels
+export const METAMASK_PROVIDER = 'metamask-provider';
+export const METAMASK_COOKIE_HANDLER = 'metamask-cookie-handler';
+export const PHISHING_SAFELIST = 'metamask-phishing-safelist';
+export const PHISHING_STREAM = 'phishing';
+
+// For more information about these legacy streams, see here:
+// https://github.com/MetaMask/metamask-extension/issues/15491
+// TODO:LegacyProvider: Delete
+export const LEGACY_CONTENT_SCRIPT = 'contentscript';
+export const LEGACY_INPAGE = 'inpage';
+export const LEGACY_PROVIDER = 'provider';
+export const LEGACY_PUBLIC_CONFIG = 'publicConfig';
diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js
index ab2483c9f9a3..d0ff7119498b 100644
--- a/app/scripts/contentscript.js
+++ b/app/scripts/contentscript.js
@@ -9,6 +9,16 @@ import {
getIsBrowserPrerenderBroken,
} from '../../shared/modules/browser-runtime.utils';
import shouldInjectProvider from '../../shared/modules/provider-injection';
+import {
+ initializeCookieHandlerSteam,
+ isDetectedCookieMarketingSite,
+} from './streams/cookie-handler-stream';
+import { logStreamDisconnectWarning } from './streams/shared';
+import {
+ METAMASK_COOKIE_HANDLER,
+ PHISHING_STREAM,
+ METAMASK_PROVIDER,
+} from './constants/stream';
// contexts
const CONTENT_SCRIPT = 'metamask-contentscript';
@@ -73,6 +83,11 @@ function setupPhishingPageStreams() {
);
phishingPageChannel = phishingPageMux.createStream(PHISHING_SAFELIST);
+ phishingPageMux.ignoreStream(METAMASK_COOKIE_HANDLER);
+ phishingPageMux.ignoreStream(LEGACY_PUBLIC_CONFIG);
+ phishingPageMux.ignoreStream(LEGACY_PROVIDER);
+ phishingPageMux.ignoreStream(METAMASK_PROVIDER);
+ phishingPageMux.ignoreStream(PHISHING_STREAM);
}
const setupPhishingExtStreams = () => {
@@ -116,6 +131,11 @@ const setupPhishingExtStreams = () => {
error,
),
);
+ phishingExtMux.ignoreStream(METAMASK_COOKIE_HANDLER);
+ phishingExtMux.ignoreStream(LEGACY_PUBLIC_CONFIG);
+ phishingExtMux.ignoreStream(LEGACY_PROVIDER);
+ phishingExtMux.ignoreStream(METAMASK_PROVIDER);
+ phishingExtMux.ignoreStream(PHISHING_STREAM);
// eslint-disable-next-line no-use-before-define
phishingExtPort.onDisconnect.addListener(onDisconnectDestroyPhishingStreams);
@@ -213,6 +233,11 @@ const setupPageStreams = () => {
);
pageChannel = pageMux.createStream(PROVIDER);
+ pageMux.ignoreStream(METAMASK_COOKIE_HANDLER);
+ pageMux.ignoreStream(LEGACY_PROVIDER);
+ pageMux.ignoreStream(LEGACY_PUBLIC_CONFIG);
+ pageMux.ignoreStream(PHISHING_SAFELIST);
+ pageMux.ignoreStream(PHISHING_STREAM);
};
// The field below is used to ensure that replay is done only once for each restart.
@@ -248,6 +273,10 @@ const setupExtensionStreams = () => {
extensionPhishingStream = extensionMux.createStream('phishing');
extensionPhishingStream.once('data', redirectToPhishingWarning);
+ extensionMux.ignoreStream(METAMASK_COOKIE_HANDLER);
+ extensionMux.ignoreStream(LEGACY_PROVIDER);
+ extensionMux.ignoreStream(PHISHING_SAFELIST);
+
// eslint-disable-next-line no-use-before-define
extensionPort.onDisconnect.addListener(onDisconnectDestroyStreams);
};
@@ -288,6 +317,11 @@ const setupLegacyPageStreams = () => {
legacyPageMux.createStream(LEGACY_PROVIDER);
legacyPagePublicConfigChannel =
legacyPageMux.createStream(LEGACY_PUBLIC_CONFIG);
+
+ legacyPageMux.ignoreStream(METAMASK_COOKIE_HANDLER);
+ legacyPageMux.ignoreStream(METAMASK_PROVIDER);
+ legacyPageMux.ignoreStream(PHISHING_SAFELIST);
+ legacyPageMux.ignoreStream(PHISHING_STREAM);
};
// TODO:LegacyProvider: Delete
@@ -331,6 +365,10 @@ const setupLegacyExtensionStreams = () => {
error,
),
);
+ legacyExtMux.ignoreStream(METAMASK_COOKIE_HANDLER);
+ legacyExtMux.ignoreStream(LEGACY_PROVIDER);
+ legacyExtMux.ignoreStream(PHISHING_SAFELIST);
+ legacyExtMux.ignoreStream(PHISHING_STREAM);
};
/**
@@ -431,19 +469,6 @@ function getNotificationTransformStream() {
return stream;
}
-/**
- * Error handler for page to extension stream disconnections
- *
- * @param {string} remoteLabel - Remote stream name
- * @param {Error} error - Stream connection error
- */
-function logStreamDisconnectWarning(remoteLabel, error) {
- console.debug(
- `MetaMask: Content script lost connection to "${remoteLabel}".`,
- error,
- );
-}
-
/**
* The function notifies inpage when the extension stream connection is ready. When the
* 'metamask_chainChanged' method is received from the extension, it implies that the
@@ -525,6 +550,10 @@ const start = () => {
return;
}
+ if (isDetectedCookieMarketingSite) {
+ initializeCookieHandlerSteam();
+ }
+
if (shouldInjectProvider()) {
initStreams();
diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js
index 8aafa0893d53..5fa34ac0cbd1 100644
--- a/app/scripts/controllers/metametrics.js
+++ b/app/scripts/controllers/metametrics.js
@@ -155,6 +155,7 @@ export default class MetaMetricsController {
participateInMetaMetrics: null,
metaMetricsId: null,
dataCollectionForMarketing: null,
+ marketingCampaignCookieId: null,
eventsBeforeMetricsOptIn: [],
traits: {},
previousUserTraits: {},
@@ -466,6 +467,8 @@ export default class MetaMetricsController {
if (participateInMetaMetrics) {
this.trackEventsAfterMetricsOptIn();
this.clearEventsAfterMetricsOptIn();
+ } else if (this.state.marketingCampaignCookieId) {
+ this.setMarketingCampaignCookieId(null);
}
///: BEGIN:ONLY_INCLUDE_IF(build-main,build-beta,build-flask)
@@ -477,10 +480,20 @@ export default class MetaMetricsController {
setDataCollectionForMarketing(dataCollectionForMarketing) {
const { metaMetricsId } = this.state;
+
this.store.updateState({ dataCollectionForMarketing });
+
+ if (!dataCollectionForMarketing && this.state.marketingCampaignCookieId) {
+ this.setMarketingCampaignCookieId(null);
+ }
+
return metaMetricsId;
}
+ setMarketingCampaignCookieId(marketingCampaignCookieId) {
+ this.store.updateState({ marketingCampaignCookieId });
+ }
+
get state() {
return this.store.getState();
}
@@ -704,6 +717,7 @@ export default class MetaMetricsController {
userAgent: window.navigator.userAgent,
page,
referrer,
+ marketingCampaignCookieId: this.state.marketingCampaignCookieId,
};
}
diff --git a/app/scripts/controllers/metametrics.test.js b/app/scripts/controllers/metametrics.test.js
index 4206de67a7fd..1df31a8d2f31 100644
--- a/app/scripts/controllers/metametrics.test.js
+++ b/app/scripts/controllers/metametrics.test.js
@@ -17,6 +17,7 @@ const VERSION = '0.0.1-test';
const FAKE_CHAIN_ID = '0x1338';
const LOCALE = 'en_US';
const TEST_META_METRICS_ID = '0xabc';
+const TEST_GA_COOKIE_ID = '123456.123455';
const DUMMY_ACTION_ID = 'DUMMY_ACTION_ID';
const MOCK_EXTENSION_ID = 'testid';
@@ -50,6 +51,7 @@ const DEFAULT_TEST_CONTEXT = {
page: METAMETRICS_BACKGROUND_PAGE_OBJECT,
referrer: undefined,
userAgent: window.navigator.userAgent,
+ marketingCampaignCookieId: null,
};
const DEFAULT_SHARED_PROPERTIES = {
@@ -113,6 +115,7 @@ const SAMPLE_NON_PERSISTED_EVENT = {
function getMetaMetricsController({
participateInMetaMetrics = true,
metaMetricsId = TEST_META_METRICS_ID,
+ marketingCampaignCookieId = null,
preferencesStore = getMockPreferencesStore(),
getCurrentChainId = () => FAKE_CHAIN_ID,
onNetworkDidChange = () => {
@@ -130,6 +133,7 @@ function getMetaMetricsController({
initState: {
participateInMetaMetrics,
metaMetricsId,
+ marketingCampaignCookieId,
fragments: {
testid: SAMPLE_PERSISTED_EVENT,
testid2: SAMPLE_NON_PERSISTED_EVENT,
@@ -160,6 +164,9 @@ describe('MetaMetricsController', function () {
expect(metaMetricsController.state.metaMetricsId).toStrictEqual(
TEST_META_METRICS_ID,
);
+ expect(
+ metaMetricsController.state.marketingCampaignCookieId,
+ ).toStrictEqual(null);
expect(metaMetricsController.locale).toStrictEqual(
LOCALE.replace('_', '-'),
);
@@ -339,6 +346,21 @@ describe('MetaMetricsController', function () {
TEST_META_METRICS_ID,
);
});
+ it('should nullify the marketingCampaignCookieId when participateInMetaMetrics is toggled off', async function () {
+ const metaMetricsController = getMetaMetricsController({
+ participateInMetaMetrics: true,
+ metaMetricsId: TEST_META_METRICS_ID,
+ dataCollectionForMarketing: true,
+ marketingCampaignCookieId: TEST_GA_COOKIE_ID,
+ });
+ expect(
+ metaMetricsController.state.marketingCampaignCookieId,
+ ).toStrictEqual(TEST_GA_COOKIE_ID);
+ await metaMetricsController.setParticipateInMetaMetrics(false);
+ expect(
+ metaMetricsController.state.marketingCampaignCookieId,
+ ).toStrictEqual(null);
+ });
});
describe('submitEvent', function () {
@@ -1252,7 +1274,65 @@ describe('MetaMetricsController', function () {
expect(Object.keys(segmentApiCalls).length === 0).toStrictEqual(true);
});
});
-
+ describe('setMarketingCampaignCookieId', function () {
+ it('should update marketingCampaignCookieId in the context when cookieId is available', async function () {
+ const metaMetricsController = getMetaMetricsController({
+ participateInMetaMetrics: true,
+ metaMetricsId: TEST_META_METRICS_ID,
+ dataCollectionForMarketing: true,
+ });
+ metaMetricsController.setMarketingCampaignCookieId(TEST_GA_COOKIE_ID);
+ expect(
+ metaMetricsController.state.marketingCampaignCookieId,
+ ).toStrictEqual(TEST_GA_COOKIE_ID);
+ const spy = jest.spyOn(segment, 'track');
+ metaMetricsController.submitEvent(
+ {
+ event: 'Fake Event',
+ category: 'Unit Test',
+ properties: {
+ test: 1,
+ },
+ },
+ { isOptIn: true },
+ );
+ expect(spy).toHaveBeenCalledTimes(1);
+ expect(spy).toHaveBeenCalledWith(
+ {
+ event: 'Fake Event',
+ anonymousId: METAMETRICS_ANONYMOUS_ID,
+ context: {
+ ...DEFAULT_TEST_CONTEXT,
+ marketingCampaignCookieId: TEST_GA_COOKIE_ID,
+ },
+ properties: {
+ test: 1,
+ ...DEFAULT_EVENT_PROPERTIES,
+ },
+ messageId: Utils.generateRandomId(),
+ timestamp: new Date(),
+ },
+ spy.mock.calls[0][1],
+ );
+ });
+ });
+ describe('setDataCollectionForMarketing', function () {
+ it('should nullify the marketingCampaignCookieId when Data collection for marketing is toggled off', async function () {
+ const metaMetricsController = getMetaMetricsController({
+ participateInMetaMetrics: true,
+ metaMetricsId: TEST_META_METRICS_ID,
+ dataCollectionForMarketing: true,
+ marketingCampaignCookieId: TEST_GA_COOKIE_ID,
+ });
+ expect(
+ metaMetricsController.state.marketingCampaignCookieId,
+ ).toStrictEqual(TEST_GA_COOKIE_ID);
+ await metaMetricsController.setDataCollectionForMarketing(false);
+ expect(
+ metaMetricsController.state.marketingCampaignCookieId,
+ ).toStrictEqual(null);
+ });
+ });
afterEach(function () {
// flush the queues manually after each test
segment.flush();
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index fbcf291e4611..3f2a6a32a25a 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -321,6 +321,7 @@ import { addDappTransaction, addTransaction } from './lib/transaction/util';
import { LatticeKeyringOffscreen } from './lib/offscreen-bridge/lattice-offscreen-keyring';
import PREINSTALLED_SNAPS from './snaps/preinstalled-snaps';
import { WeakRefObjectMap } from './lib/WeakRefObjectMap';
+import { METAMASK_COOKIE_HANDLER } from './constants/stream';
// Notification controllers
import { PushPlatformNotificationsController } from './controllers/push-platform-notifications/push-platform-notifications';
@@ -3142,6 +3143,10 @@ export default class MetamaskController extends EventEmitter {
metaMetricsController.setDataCollectionForMarketing.bind(
metaMetricsController,
),
+ setMarketingCampaignCookieId:
+ metaMetricsController.setMarketingCampaignCookieId.bind(
+ metaMetricsController,
+ ),
setCurrentLocale: preferencesController.setCurrentLocale.bind(
preferencesController,
),
@@ -5057,6 +5062,42 @@ export default class MetamaskController extends EventEmitter {
);
}
+ setUpCookieHandlerCommunication({ connectionStream }) {
+ const {
+ metaMetricsId,
+ dataCollectionForMarketing,
+ participateInMetaMetrics,
+ } = this.metaMetricsController.store.getState();
+
+ if (
+ metaMetricsId &&
+ dataCollectionForMarketing &&
+ participateInMetaMetrics
+ ) {
+ // setup multiplexing
+ const mux = setupMultiplex(connectionStream);
+ const metamaskCookieHandlerStream = mux.createStream(
+ METAMASK_COOKIE_HANDLER,
+ );
+ // set up postStream transport
+ metamaskCookieHandlerStream.on(
+ 'data',
+ createMetaRPCHandler(
+ {
+ getCookieFromMarketingPage:
+ this.getCookieFromMarketingPage.bind(this),
+ },
+ metamaskCookieHandlerStream,
+ ),
+ );
+ }
+ }
+
+ getCookieFromMarketingPage(data) {
+ const { ga_client_id: cookieId } = data;
+ this.metaMetricsController.setMarketingCampaignCookieId(cookieId);
+ }
+
/**
* Called when we detect a suspicious domain. Requests the browser redirects
* to our anti-phishing page.
diff --git a/app/scripts/streams/cookie-handler-stream.ts b/app/scripts/streams/cookie-handler-stream.ts
new file mode 100644
index 000000000000..1b218e8d0cec
--- /dev/null
+++ b/app/scripts/streams/cookie-handler-stream.ts
@@ -0,0 +1,193 @@
+import browser from 'webextension-polyfill';
+import { WindowPostMessageStream } from '@metamask/post-message-stream';
+import ObjectMultiplex from '@metamask/object-multiplex';
+// eslint-disable-next-line @typescript-eslint/ban-ts-comment
+// @ts-expect-error types/readable-stream.d.ts does not get picked up by ts-node
+import { pipeline } from 'readable-stream';
+import { Substream } from '@metamask/object-multiplex/dist/Substream';
+import PortStream from 'extension-port-stream';
+import { EXTENSION_MESSAGES } from '../../../shared/constants/app';
+import { COOKIE_ID_MARKETING_WHITELIST_ORIGINS } from '../constants/marketing-site-whitelist';
+import { checkForLastError } from '../../../shared/modules/browser-runtime.utils';
+import {
+ METAMASK_COOKIE_HANDLER,
+ CONTENT_SCRIPT,
+ LEGACY_PUBLIC_CONFIG,
+ METAMASK_PROVIDER,
+ PHISHING_SAFELIST,
+ LEGACY_PROVIDER,
+ PHISHING_STREAM,
+} from '../constants/stream';
+import { logStreamDisconnectWarning } from './shared';
+
+export const isDetectedCookieMarketingSite: boolean =
+ COOKIE_ID_MARKETING_WHITELIST_ORIGINS.some(
+ (origin) => origin === window.location.origin,
+ );
+
+let cookieHandlerPageMux: ObjectMultiplex,
+ cookieHandlerPageChannel: Substream,
+ cookieHandlerExtPort: browser.Runtime.Port,
+ cookieHandlerExtStream: PortStream | null,
+ cookieHandlerMux: ObjectMultiplex,
+ cookieHandlerExtChannel: Substream;
+
+function setupCookieHandlerStreamsFromOrigin(origin: string): void {
+ const cookieHandlerPageStream = new WindowPostMessageStream({
+ name: CONTENT_SCRIPT,
+ target: 'CookieHandlerPage',
+ targetWindow: window,
+ targetOrigin: origin,
+ });
+
+ // create and connect channel muxers
+ // so we can handle the channels individually
+ cookieHandlerPageMux = new ObjectMultiplex();
+ cookieHandlerPageMux.setMaxListeners(25);
+
+ pipeline(
+ cookieHandlerPageMux,
+ cookieHandlerPageStream,
+ cookieHandlerPageMux,
+ (err: Error) =>
+ logStreamDisconnectWarning('MetaMask Inpage Multiplex', err),
+ );
+
+ cookieHandlerPageChannel = cookieHandlerPageMux.createStream(
+ METAMASK_COOKIE_HANDLER,
+ );
+ cookieHandlerPageMux.ignoreStream(LEGACY_PUBLIC_CONFIG);
+ cookieHandlerPageMux.ignoreStream(LEGACY_PROVIDER);
+ cookieHandlerPageMux.ignoreStream(METAMASK_PROVIDER);
+ cookieHandlerPageMux.ignoreStream(PHISHING_SAFELIST);
+ cookieHandlerPageMux.ignoreStream(PHISHING_STREAM);
+}
+
+/**
+ * establishes a communication stream between the content script and background.js
+ */
+export const setupCookieHandlerExtStreams = (): void => {
+ cookieHandlerExtPort = browser.runtime.connect({
+ name: CONTENT_SCRIPT,
+ });
+ cookieHandlerExtStream = new PortStream(cookieHandlerExtPort);
+
+ // create and connect channel muxers
+ // so we can handle the channels individually
+ cookieHandlerMux = new ObjectMultiplex();
+ cookieHandlerMux.setMaxListeners(25);
+
+ pipeline(
+ cookieHandlerMux,
+ cookieHandlerExtStream,
+ cookieHandlerMux,
+ (err: Error) => {
+ logStreamDisconnectWarning('MetaMask Background Multiplex', err);
+ window.postMessage(
+ {
+ target: 'CookieHandlerPage',
+ data: {
+ // this object gets passed to @metamask/object-multiplex
+ name: METAMASK_COOKIE_HANDLER, // the @metamask/object-multiplex channel name
+ data: {
+ jsonrpc: '2.0',
+ method: 'METAMASK_STREAM_FAILURE',
+ },
+ },
+ },
+ window.location.origin,
+ );
+ },
+ );
+
+ // forward communication across inpage-background for these channels only
+ cookieHandlerExtChannel = cookieHandlerMux.createStream(
+ METAMASK_COOKIE_HANDLER,
+ );
+ cookieHandlerMux.ignoreStream(LEGACY_PUBLIC_CONFIG);
+ cookieHandlerMux.ignoreStream(LEGACY_PROVIDER);
+ cookieHandlerMux.ignoreStream(METAMASK_PROVIDER);
+ cookieHandlerMux.ignoreStream(PHISHING_SAFELIST);
+ cookieHandlerMux.ignoreStream(PHISHING_STREAM);
+ pipeline(
+ cookieHandlerPageChannel,
+ cookieHandlerExtChannel,
+ cookieHandlerPageChannel,
+ (error: Error) =>
+ console.debug(
+ `MetaMask: Muxed traffic for channel "${METAMASK_COOKIE_HANDLER}" failed.`,
+ error,
+ ),
+ );
+
+ cookieHandlerExtPort.onDisconnect.addListener(
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
+ onDisconnectDestroyCookieStreams,
+ );
+};
+
+/** Destroys all of the cookie handler extension streams */
+const destroyCookieExtStreams = () => {
+ cookieHandlerPageChannel.removeAllListeners();
+
+ cookieHandlerMux.removeAllListeners();
+ cookieHandlerMux.destroy();
+
+ cookieHandlerExtChannel.removeAllListeners();
+ cookieHandlerExtChannel.destroy();
+
+ cookieHandlerExtStream = null;
+};
+
+/**
+ * This listener destroys the phishing extension streams when the extension port is disconnected,
+ * so that streams may be re-established later the phishing extension port is reconnected.
+ */
+const onDisconnectDestroyCookieStreams = () => {
+ const err = checkForLastError();
+
+ cookieHandlerExtPort.onDisconnect.removeListener(
+ onDisconnectDestroyCookieStreams,
+ );
+
+ destroyCookieExtStreams();
+
+ /**
+ * If an error is found, reset the streams. When running two or more dapps, resetting the service
+ * worker may cause the error, "Error: Could not establish connection. Receiving end does not
+ * exist.", due to a race-condition. The disconnect event may be called by runtime.connect which
+ * may cause issues. We suspect that this is a chromium bug as this event should only be called
+ * once the port and connections are ready. Delay time is arbitrary.
+ */
+ if (err) {
+ console.warn(`${err} Resetting the phishing streams.`);
+ setTimeout(setupCookieHandlerExtStreams, 1000);
+ }
+};
+
+const onMessageSetUpCookieHandlerStreams = (msg: {
+ name: string;
+ origin: string;
+}): Promise | undefined => {
+ if (msg.name === EXTENSION_MESSAGES.READY) {
+ if (!cookieHandlerExtStream) {
+ setupCookieHandlerExtStreams();
+ }
+ return Promise.resolve(
+ `MetaMask: handled "${EXTENSION_MESSAGES.READY}" for phishing streams`,
+ );
+ }
+ return undefined;
+};
+
+/**
+ * Initializes two-way communication streams between the browser extension and
+ * the cookie id submission page context. This function also creates an event listener to
+ * reset the streams if the service worker resets.
+ */
+export const initializeCookieHandlerSteam = (): void => {
+ const { origin } = window.location;
+ setupCookieHandlerStreamsFromOrigin(origin);
+ setupCookieHandlerExtStreams();
+ browser.runtime.onMessage.addListener(onMessageSetUpCookieHandlerStreams);
+};
diff --git a/app/scripts/streams/shared.ts b/app/scripts/streams/shared.ts
new file mode 100644
index 000000000000..73dc6ec1d6e5
--- /dev/null
+++ b/app/scripts/streams/shared.ts
@@ -0,0 +1,15 @@
+/**
+ * Error handler for page to extension stream disconnections
+ *
+ * @param remoteLabel - Remote stream name
+ * @param error - Stream connection error
+ */
+export function logStreamDisconnectWarning(
+ remoteLabel: string,
+ error: Error,
+): void {
+ console.debug(
+ `MetaMask: Content script lost connection to "${remoteLabel}".`,
+ error,
+ );
+}
diff --git a/test/e2e/tests/metrics/marketing-cookieid-mock-page/index.html b/test/e2e/tests/metrics/marketing-cookieid-mock-page/index.html
new file mode 100644
index 000000000000..9233e3bf6a34
--- /dev/null
+++ b/test/e2e/tests/metrics/marketing-cookieid-mock-page/index.html
@@ -0,0 +1,35 @@
+
+
+
+ Mock E2E Cookie Handler
+
+
+
+ Mock Page for E2E Cookie Handler
+
-
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.test.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.test.tsx
index daca28ece848..e85ffa28b227 100644
--- a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.test.tsx
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.test.tsx
@@ -1,24 +1,41 @@
import React from 'react';
import configureMockStore from 'redux-mock-store';
+import { act } from 'react-dom/test-utils';
import mockState from '../../../../../../../../test/data/mock-state.json';
+// import { getMockTypedSignConfirmStateForRequest } from '../../../../../../../../test/data/confirmations/helper';
import { renderWithProvider } from '../../../../../../../../test/lib/render-helpers';
+// TODO: readd in 12.4.0
+// import { renderWithConfirmContextProvider } from '../../../../../../../../test/lib/confirmations/render-helpers';
import { permitSignatureMsg } from '../../../../../../../../test/data/confirmations/typed_sign';
import PermitSimulation from './permit-simulation';
+jest.mock('../../../../../../../store/actions', () => {
+ return {
+ getTokenStandardAndDetails: jest.fn().mockResolvedValue({ decimals: 2 }),
+ };
+});
+
describe('PermitSimulation', () => {
- it('renders component correctly', () => {
+ it('renders component correctly', async () => {
const state = {
...mockState,
confirm: {
currentConfirmation: permitSignatureMsg,
},
};
+ // TODO: readd in 12.4.0
+ // const state = getMockTypedSignConfirmStateForRequest(permitSignatureMsg);
const mockStore = configureMockStore([])(state);
- const { container } = renderWithProvider(
- ,
- mockStore,
- );
- expect(container).toMatchSnapshot();
+
+ await act(async () => {
+ const { container, findByText } = renderWithProvider(
+ ,
+ mockStore,
+ );
+
+ expect(await findByText('30')).toBeInTheDocument();
+ expect(container).toMatchSnapshot();
+ });
});
});
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx
index e5e9529a516a..b246c2816d4d 100644
--- a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/permit-simulation.tsx
@@ -1,69 +1,61 @@
-import React, { useMemo } from 'react';
+import React from 'react';
import { useSelector } from 'react-redux';
-import { NameType } from '@metamask/name-controller';
-import { calcTokenAmount } from '../../../../../../../../shared/lib/transactions-controller-utils';
+import { PrimaryType } from '../../../../../../../../shared/constants/signatures';
import { parseTypedDataMessage } from '../../../../../../../../shared/modules/transaction.utils';
-import { Numeric } from '../../../../../../../../shared/modules/Numeric';
-import Name from '../../../../../../../components/app/name/name';
import {
ConfirmInfoRow,
ConfirmInfoRowText,
} from '../../../../../../../components/app/confirm/info/row';
-import { shortenString } from '../../../../../../../helpers/utils/util';
import { useI18nContext } from '../../../../../../../hooks/useI18nContext';
import { currentConfirmationSelector } from '../../../../../../../selectors';
-import { Box, Text } from '../../../../../../../components/component-library';
-import Tooltip from '../../../../../../../components/ui/tooltip';
+import { Box } from '../../../../../../../components/component-library';
import {
- BackgroundColor,
- BlockSize,
- BorderRadius,
Display,
- TextAlign,
+ FlexDirection,
} from '../../../../../../../helpers/constants/design-system';
import { SignatureRequestType } from '../../../../../types/confirm';
-import useTokenExchangeRate from '../../../../../../../components/app/currency-input/hooks/useTokenExchangeRate';
-import { IndividualFiatDisplay } from '../../../../simulation-details/fiat-display';
-import {
- formatAmount,
- formatAmountMaxPrecision,
-} from '../../../../simulation-details/formatAmount';
import { ConfirmInfoSection } from '../../../../../../../components/app/confirm/info/row/section';
+import PermitSimulationValueDisplay from './value-display/value-display';
+
+function extractTokenDetailsByPrimaryType(
+ message: Record,
+ primaryType: PrimaryType,
+): object[] | unknown {
+ let tokenDetails;
+
+ switch (primaryType) {
+ case PrimaryType.PermitBatch:
+ case PrimaryType.PermitSingle:
+ tokenDetails = message?.details;
+ break;
+ case PrimaryType.PermitBatchTransferFrom:
+ case PrimaryType.PermitTransferFrom:
+ tokenDetails = message?.permitted;
+ break;
+ default:
+ break;
+ }
+
+ const isNonArrayObject = tokenDetails && !Array.isArray(tokenDetails);
-const PermitSimulation: React.FC<{
- tokenDecimals: number;
-}> = ({ tokenDecimals }) => {
+ return isNonArrayObject ? [tokenDetails] : tokenDetails;
+}
+
+const PermitSimulation: React.FC = () => {
const t = useI18nContext();
const currentConfirmation = useSelector(
currentConfirmationSelector,
) as SignatureRequestType;
+ const msgData = currentConfirmation.msgParams?.data;
const {
domain: { verifyingContract },
- message: { value },
- } = parseTypedDataMessage(currentConfirmation.msgParams?.data as string);
-
- const exchangeRate = useTokenExchangeRate(verifyingContract);
-
- const fiatValue = useMemo(() => {
- if (exchangeRate && value) {
- return exchangeRate.times(new Numeric(value, 10)).toNumber();
- }
- return undefined;
- }, [exchangeRate, value]);
-
- const { tokenValue, tokenValueMaxPrecision } = useMemo(() => {
- if (!value) {
- return { tokenValue: null, tokenValueMaxPrecision: null };
- }
- const tokenAmount = calcTokenAmount(value, tokenDecimals);
+ message,
+ primaryType,
+ } = parseTypedDataMessage(msgData as string);
- return {
- tokenValue: formatAmount('en-US', tokenAmount),
- tokenValueMaxPrecision: formatAmountMaxPrecision('en-US', tokenAmount),
- };
- }, [tokenDecimals, value]);
+ const tokenDetails = extractTokenDetailsByPrimaryType(message, primaryType);
return (
@@ -75,42 +67,32 @@ const PermitSimulation: React.FC<{
-
+ {Array.isArray(tokenDetails) ? (
-
-
- {shortenString(tokenValue || '', {
- truncatedCharLimit: 15,
- truncatedStartChars: 15,
- truncatedEndChars: 0,
- skipCharacterInEnd: true,
- })}
-
-
+ {tokenDetails.map(
+ (
+ { token, amount }: { token: string; amount: string },
+ i: number,
+ ) => (
+
+ ),
+ )}
-
-
-
- {fiatValue && (
-
- )}
-
+ ) : (
+
+ )}
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/__snapshots__/value-display.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/__snapshots__/value-display.test.tsx.snap
new file mode 100644
index 000000000000..022ff8b6dbc2
--- /dev/null
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/__snapshots__/value-display.test.tsx.snap
@@ -0,0 +1,56 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PermitSimulationValueDisplay renders component correctly 1`] = `
+
+
+
+
+
+
+
+
+ 0xA0b86...6eB48
+
+
+
+
+
+
+
+`;
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/value-display.test.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/value-display.test.tsx
new file mode 100644
index 000000000000..f6af7357502d
--- /dev/null
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/value-display.test.tsx
@@ -0,0 +1,32 @@
+import React from 'react';
+import { act } from 'react-dom/test-utils';
+import configureMockStore from 'redux-mock-store';
+
+import mockState from '../../../../../../../../../test/data/mock-state.json';
+import { renderWithProvider } from '../../../../../../../../../test/lib/render-helpers';
+import PermitSimulationValueDisplay from './value-display';
+
+jest.mock('../../../../../../../../store/actions', () => {
+ return {
+ getTokenStandardAndDetails: jest.fn().mockResolvedValue({ decimals: 4 }),
+ };
+});
+
+describe('PermitSimulationValueDisplay', () => {
+ it('renders component correctly', async () => {
+ const mockStore = configureMockStore([])(mockState);
+
+ await act(async () => {
+ const { container, findByText } = renderWithProvider(
+ ,
+ mockStore,
+ );
+
+ expect(await findByText('0.432')).toBeInTheDocument();
+ expect(container).toMatchSnapshot();
+ });
+ });
+});
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/value-display.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/value-display.tsx
new file mode 100644
index 000000000000..d0cd9c529d0e
--- /dev/null
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/permit-simulation/value-display/value-display.tsx
@@ -0,0 +1,121 @@
+import React, { useMemo } from 'react';
+import { NameType } from '@metamask/name-controller';
+import { captureException } from '@sentry/browser';
+import { getTokenStandardAndDetails } from '../../../../../../../../store/actions';
+import { shortenString } from '../../../../../../../../helpers/utils/util';
+
+import { calcTokenAmount } from '../../../../../../../../../shared/lib/transactions-controller-utils';
+import useTokenExchangeRate from '../../../../../../../../components/app/currency-input/hooks/useTokenExchangeRate';
+import { IndividualFiatDisplay } from '../../../../../simulation-details/fiat-display';
+import {
+ formatAmount,
+ formatAmountMaxPrecision,
+} from '../../../../../simulation-details/formatAmount';
+import { useAsyncResult } from '../../../../../../../../hooks/useAsyncResult';
+
+import {
+ Box,
+ Text,
+} from '../../../../../../../../components/component-library';
+import Tooltip from '../../../../../../../../components/ui/tooltip';
+import {
+ BackgroundColor,
+ BlockSize,
+ BorderRadius,
+ Display,
+ JustifyContent,
+ TextAlign,
+} from '../../../../../../../../helpers/constants/design-system';
+import Name from '../../../../../../../../components/app/name/name';
+
+const getTokenDecimals = async (tokenContract: string) => {
+ const tokenDetails = await getTokenStandardAndDetails(tokenContract);
+ const tokenDecimals = tokenDetails?.decimals;
+
+ return parseInt(tokenDecimals ?? '0', 10);
+};
+
+const PermitSimulationValueDisplay: React.FC<{
+ primaryType?: string;
+ tokenContract: string;
+ value: number | string;
+}> = ({ primaryType, tokenContract, value }) => {
+ const exchangeRate = useTokenExchangeRate(tokenContract);
+
+ const { value: tokenDecimals } = useAsyncResult(
+ async () => await getTokenDecimals(tokenContract),
+ [tokenContract],
+ );
+
+ const fiatValue = useMemo(() => {
+ if (exchangeRate && value) {
+ const tokenAmount = calcTokenAmount(value, tokenDecimals);
+ return exchangeRate.times(tokenAmount).toNumber();
+ }
+ return undefined;
+ }, [exchangeRate, tokenDecimals, value]);
+
+ const { tokenValue, tokenValueMaxPrecision } = useMemo(() => {
+ if (!value) {
+ return { tokenValue: null, tokenValueMaxPrecision: null };
+ }
+
+ const tokenAmount = calcTokenAmount(value, tokenDecimals);
+
+ return {
+ tokenValue: formatAmount('en-US', tokenAmount),
+ tokenValueMaxPrecision: formatAmountMaxPrecision('en-US', tokenAmount),
+ };
+ }, [tokenDecimals, value]);
+
+ /** Temporary error capturing as we are building out Permit Simulations */
+ if (!tokenContract) {
+ captureException(
+ new Error(
+ `PermitSimulationValueDisplay: Token contract address is missing where primaryType === ${primaryType}`,
+ ),
+ );
+ return null;
+ }
+
+ return (
+
+
+
+
+
+ {shortenString(tokenValue || '', {
+ truncatedCharLimit: 15,
+ truncatedStartChars: 15,
+ truncatedEndChars: 0,
+ skipCharacterInEnd: true,
+ })}
+
+
+
+
+
+
+ {fiatValue && }
+
+
+ );
+};
+
+export default PermitSimulationValueDisplay;
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx
index 48e7f6b64941..ddb56bf82800 100644
--- a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.tsx
@@ -58,9 +58,7 @@ const TypedSignInfo: React.FC = () => {
return (
<>
- {isPermit && useTransactionSimulations && (
-
- )}
+ {isPermit && useTransactionSimulations && }
{isPermit && (
<>
diff --git a/ui/pages/confirmations/components/confirm/row/dataTree.tsx b/ui/pages/confirmations/components/confirm/row/dataTree.tsx
index 2b38ccee5663..f728b9d5dfa9 100644
--- a/ui/pages/confirmations/components/confirm/row/dataTree.tsx
+++ b/ui/pages/confirmations/components/confirm/row/dataTree.tsx
@@ -73,12 +73,10 @@ const getTokenDecimalsOfDataTree = async (
return undefined;
}
- const decimals = parseInt(
- (await getTokenStandardAndDetails(tokenContract))?.decimals ?? '0',
- 10,
- );
+ const tokenDetails = await getTokenStandardAndDetails(tokenContract);
+ const tokenDecimals = tokenDetails?.decimals;
- return decimals;
+ return parseInt(tokenDecimals ?? '0', 10);
};
export const DataTree = ({
diff --git a/ui/pages/confirmations/confirm/__snapshots__/confirm.test.tsx.snap b/ui/pages/confirmations/confirm/__snapshots__/confirm.test.tsx.snap
index ef4508c65552..84bab3847b1e 100644
--- a/ui/pages/confirmations/confirm/__snapshots__/confirm.test.tsx.snap
+++ b/ui/pages/confirmations/confirm/__snapshots__/confirm.test.tsx.snap
@@ -225,6 +225,1814 @@ exports[`Confirm matches snapshot for signature - personal sign type 1`] = `
`;
+exports[`Confirm should match snapshot for signature - typed sign - V4 - PermitBatch 1`] = `
+
+
+
+
+
+
+
+ Spending cap request
+
+
+ This site wants permission to spend your tokens.
+
+
+
+
+
+ Estimated changes
+
+
+
+
+
+ You're giving the spender permission to spend this many tokens from your account.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 14,615,016,373,...
+
+
+
+
+
+
+
+
+ 0xA0b86...6eB48
+
+
+
+
+
+
+
+
+
+
+
+
+ 24,615,016,373,...
+
+
+
+
+
+
+
+
+ 0xb0B86...6EB48
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0x3fC91...b7FAD
+
+
+
+
+
+
+
+
+
+ metamask.github.io
+
+
+
+
+
+
+
+
+
+ 0x00000...78BA3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0xA0b86...6eB48
+
+
+
+
+
+
+
+
+
+
+ 14,615,016,373,...
+
+
+
+
+
+
+
+
+
+ 20 January 1970, 22:34
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0xb0B86...6EB48
+
+
+
+
+
+
+
+
+
+
+ 24,615,016,373,...
+
+
+
+
+
+
+
+
+
+ 20 January 1970, 22:34
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0x3fC91...b7FAD
+
+
+
+
+
+
+
+
+ 20 January 1970, 21:51
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`Confirm should match snapshot for signature - typed sign - V4 - PermitSingle 1`] = `
+
+
+
+
+
+
+
+ Spending cap request
+
+
+ This site wants permission to spend your tokens.
+
+
+
+
+
+ Estimated changes
+
+
+
+
+
+ You're giving the spender permission to spend this many tokens from your account.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 14,615,016,373,...
+
+
+
+
+
+
+
+
+ 0xA0b86...6eB48
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0x3fC91...b7FAD
+
+
+
+
+
+
+
+
+
+ metamask.github.io
+
+
+
+
+
+
+
+
+
+ 0x00000...78BA3
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0xA0b86...6eB48
+
+
+
+
+
+
+
+
+
+
+ 14,615,016,373,...
+
+
+
+
+
+
+
+
+
+ 20 January 1970, 22:34
+
+
+
+
+
+
+
+
+
+
+
+
+ 0x3fC91...b7FAD
+
+
+
+
+
+
+
+
+ 20 January 1970, 21:51
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
exports[`Confirm should match snapshot for signature - typed sign - V4 1`] = `
- C
+
+ />
+ />
+ />
+ />
+ />
+ />
{
expect(container).toMatchSnapshot();
});
+ // TODO: re-add for 12.4.0
+ // it('matches snapshot for signature - personal sign type', async () => {
+ // const mockStatePersonalSign = getMockPersonalSignConfirmState();
+ // const mockStore = configureMockStore(middleware)(mockStatePersonalSign);
+
+ // await act(async () => {
+ // const { container } = await renderWithConfirmContextProvider(
+ // ,
+ // mockStore,
+ // );
+ // expect(container).toMatchSnapshot();
+ // });
+ // });
+
it('should match snapshot signature - typed sign - order', async () => {
const mockStateTypedSign = {
...mockState,
@@ -113,7 +129,85 @@ describe('Confirm', () => {
confirm: { currentConfirmation: unapprovedTypedSignMsgV4 },
};
const mockStore = configureMockStore(middleware)(mockStateTypedSign);
- const { container } = renderWithProvider( , mockStore);
- expect(container).toMatchSnapshot();
+
+ await act(async () => {
+ // TODO: re-add for 12.4.0
+ // const { container } = await renderWithConfirmContextProvider(
+ const { container } = renderWithProvider( , mockStore);
+
+ expect(container).toMatchSnapshot();
+ });
+ });
+
+ it('should match snapshot for signature - typed sign - V4 - PermitSingle', async () => {
+ const mockStateTypedSign = {
+ ...mockState,
+ metamask: {
+ ...mockState.metamask,
+ useTransactionSimulations: true,
+ },
+ confirm: { currentConfirmation: permitSingleSignatureMsg },
+ };
+ // TODO: re-add for 12.4.0
+ // const mockStateTypedSign = getMockTypedSignConfirmStateForRequest(
+ // permitSingleSignatureMsg,
+ // {
+ // metamask: { useTransactionSimulations: true },
+ // },
+ // );
+ const mockStore = configureMockStore(middleware)(mockStateTypedSign);
+
+ jest.spyOn(actions, 'getTokenStandardAndDetails').mockResolvedValue({
+ decimals: '2',
+ standard: 'erc20',
+ });
+
+ await act(async () => {
+ // TODO: re-add for 12.4.0
+ // const { container, findByText } = await renderWithConfirmContextProvider(
+ const { container, findByText } = renderWithProvider(
+ ,
+ mockStore,
+ );
+
+ expect(await findByText('1,461,501,637,3...')).toBeInTheDocument();
+ expect(container).toMatchSnapshot();
+ });
+ });
+
+ it('should match snapshot for signature - typed sign - V4 - PermitBatch', async () => {
+ const mockStateTypedSign = {
+ ...mockState,
+ metamask: {
+ ...mockState.metamask,
+ useTransactionSimulations: true,
+ },
+ confirm: { currentConfirmation: permitBatchSignatureMsg },
+ };
+ // TODO: re-add for 12.4.0
+ // const mockStateTypedSign = getMockTypedSignConfirmStateForRequest(
+ // permitBatchSignatureMsg,
+ // {
+ // metamask: { useTransactionSimulations: true },
+ // },
+ // );
+ const mockStore = configureMockStore(middleware)(mockStateTypedSign);
+
+ jest.spyOn(actions, 'getTokenStandardAndDetails').mockResolvedValue({
+ decimals: '2',
+ standard: 'erc20',
+ });
+
+ await act(async () => {
+ // TODO: re-add for 12.4.0
+ // const { container, findByText } = await renderWithConfirmContextProvider(
+ const { container, findByText } = renderWithProvider(
+ ,
+ mockStore,
+ );
+
+ expect(await findByText('1,461,501,637,3...')).toBeInTheDocument();
+ expect(container).toMatchSnapshot();
+ });
});
});
From 4c4b5c76b50afa76ef6d8e575d1ca70fa6159fa7 Mon Sep 17 00:00:00 2001
From: Pedro Figueiredo
Date: Mon, 23 Sep 2024 14:57:40 +0100
Subject: [PATCH 34/43] =?UTF-8?q?cherry-pick:=20feat:=20Add=20experimental?=
=?UTF-8?q?=20settings=20toggle=20for=20transactions=20redesign=20(#26?=
=?UTF-8?q?=E2=80=A6=20(#27166)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
…010)
Cherry-pick PR https://github.com/MetaMask/metamask-extension/pull/26010
into Version-v12.3.0
## **Description**
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27166?quickstart=1)
## **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 Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
ui/pages/confirmations/hooks/useCurrentConfirmation.ts | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/ui/pages/confirmations/hooks/useCurrentConfirmation.ts b/ui/pages/confirmations/hooks/useCurrentConfirmation.ts
index 575f7d686e67..2403622f5a0e 100644
--- a/ui/pages/confirmations/hooks/useCurrentConfirmation.ts
+++ b/ui/pages/confirmations/hooks/useCurrentConfirmation.ts
@@ -60,11 +60,9 @@ const useCurrentConfirmation = () => {
selectUnapprovedMessage(state, confirmationId),
);
- const isCorrectTransactionType =
- isRedesignedConfirmationsDeveloperSettingEnabled &&
- REDESIGN_TRANSACTION_TYPES.includes(
- transactionMetadata?.type as TransactionType,
- );
+ const isCorrectTransactionType = REDESIGN_TRANSACTION_TYPES.includes(
+ transactionMetadata?.type as TransactionType,
+ );
const isCorrectApprovalType = REDESIGN_APPROVAL_TYPES.includes(
pendingApproval?.type as ApprovalType,
From e5a2159f3b6d3beef6cfd3cd5dab71661d1ddc38 Mon Sep 17 00:00:00 2001
From: Ariella Vu <20778143+digiwand@users.noreply.github.com>
Date: Mon, 23 Sep 2024 21:59:59 +0800
Subject: [PATCH 35/43] fix: [cherrypick][V12.3.0] Redesign Signature Message
date values (#27305)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Cherry-pick https://github.com/MetaMask/metamask-extension/pull/27249
for v12.3.0
Fix date values:
- Formerly, conversations were converting values as if they were
milliseconds. However, these values come from Solidity where these
timestamps are unix timestamps in seconds.
- Support -1 (no expiration) value
- Display "expiry" as a date instead of a unix timestamp
This PR fixes the conversion.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27249?quickstart=1)
Fixes: https://github.com/MetaMask/metamask-extension/issues/27137
1. Go to test-dapp
2. Request Permit or another TypedSign request
3. Observe deadlines and dates
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
- [ ] 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/_locales/en/messages.json | 3 +
test/data/confirmations/typed_sign.ts | 27 +-
.../confirmations/signatures/permit.spec.ts | 2 +-
.../app/confirm/info/row/date.stories.tsx | 4 +-
.../app/confirm/info/row/date.test.tsx | 4 +-
ui/components/app/confirm/info/row/date.tsx | 11 +-
ui/helpers/utils/util.js | 14 +-
ui/helpers/utils/util.test.js | 8 +-
.../personal-sign/siwe-sign/siwe-sign.tsx | 4 +-
.../__snapshots__/typed-sign.test.tsx.snap | 589 +++++++++++++++++-
.../info/typed-sign/typed-sign.test.tsx | 17 +
.../row/__snapshots__/dataTree.test.tsx.snap | 99 +++
.../components/confirm/row/dataTree.test.tsx | 13 +
.../components/confirm/row/dataTree.tsx | 23 +-
.../__snapshots__/confirm.test.tsx.snap | 12 +-
15 files changed, 801 insertions(+), 29 deletions(-)
diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json
index c3683becebbd..75ff076121df 100644
--- a/app/_locales/en/messages.json
+++ b/app/_locales/en/messages.json
@@ -3253,6 +3253,9 @@
"nonceFieldHeading": {
"message": "Custom nonce"
},
+ "none": {
+ "message": "None"
+ },
"notBusy": {
"message": "Not busy"
},
diff --git a/test/data/confirmations/typed_sign.ts b/test/data/confirmations/typed_sign.ts
index 3dd236ca9fa6..a63423e17ae9 100644
--- a/test/data/confirmations/typed_sign.ts
+++ b/test/data/confirmations/typed_sign.ts
@@ -1,3 +1,4 @@
+import { TransactionType } from '@metamask/transaction-controller';
import { SignatureRequestType } from '../../../ui/pages/confirmations/types/confirm';
export const unapprovedTypedSignMsgV1 = {
@@ -169,12 +170,13 @@ export const permitSignatureMsg = {
data: '{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Permit":[{"name":"owner","type":"address"},{"name":"spender","type":"address"},{"name":"value","type":"uint256"},{"name":"nonce","type":"uint256"},{"name":"deadline","type":"uint256"}]},"primaryType":"Permit","domain":{"name":"MyToken","version":"1","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC","chainId":1},"message":{"owner":"0x935e73edb9ff52e23bac7f7e043a1ecd06d05477","spender":"0x5B38Da6a701c568545dCfcB03FcB875f56beddC4","value":3000,"nonce":0,"deadline":50000000000}}',
from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477',
version: 'V4',
+ requestId: 14,
signatureMethod: 'eth_signTypedData_v4',
origin: 'https://metamask.github.io',
},
} as SignatureRequestType;
-export const permitBatchSignatureMsg = {
+export const permitSignatureMsgWithNoDeadline = {
id: '0b1787a0-1c44-11ef-b70d-e7064bd7b659',
securityAlertResponse: {
reason: 'loading',
@@ -184,10 +186,30 @@ export const permitBatchSignatureMsg = {
status: 'unapproved',
time: 1716826404122,
type: 'eth_signTypedData',
+ msgParams: {
+ data: '{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Permit":[{"name":"owner","type":"address"},{"name":"spender","type":"address"},{"name":"value","type":"uint256"},{"name":"nonce","type":"uint256"},{"name":"deadline","type":"uint256"}]},"primaryType":"Permit","domain":{"name":"MyToken","version":"1","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC","chainId":1},"message":{"owner":"0x935e73edb9ff52e23bac7f7e043a1ecd06d05477","spender":"0x5B38Da6a701c568545dCfcB03FcB875f56beddC4","value":3000,"nonce":0,"deadline":-1}}',
+ from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477',
+ version: 'V4',
+ signatureMethod: 'eth_signTypedData_v4',
+ origin: 'https://metamask.github.io',
+ },
+} as SignatureRequestType;
+
+export const permitBatchSignatureMsg = {
+ id: '0b1787a0-1c44-11ef-b70d-e7064bd7b659',
+ securityAlertResponse: {
+ reason: 'loading',
+ result_type: 'validation_in_progress',
+ securityAlertId: 'ab21395f-2190-472f-8cfa-3d224e7529d8',
+ },
+ status: 'unapproved',
+ time: 1716826404122,
+ type: TransactionType.signTypedData,
msgParams: {
data: '{"types":{"PermitBatch":[{"name":"details","type":"PermitDetails[]"},{"name":"spender","type":"address"},{"name":"sigDeadline","type":"uint256"}],"PermitDetails":[{"name":"token","type":"address"},{"name":"amount","type":"uint160"},{"name":"expiration","type":"uint48"},{"name":"nonce","type":"uint48"}],"EIP712Domain":[{"name":"name","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}]},"domain":{"name":"Permit2","chainId":"1","verifyingContract":"0x000000000022d473030f116ddee9f6b43ac78ba3"},"primaryType":"PermitBatch","message":{"details":[{"token":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","amount":"1461501637330902918203684832716283019655932542975","expiration":"1722887542","nonce":"5"},{"token":"0xb0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","amount":"2461501637330902918203684832716283019655932542975","expiration":"1722887642","nonce":"6"}],"spender":"0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad","sigDeadline":"1720297342"}}',
from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477',
version: 'V4',
+ requestId: 15,
signatureMethod: 'eth_signTypedData_v4',
origin: 'https://metamask.github.io',
},
@@ -202,11 +224,12 @@ export const permitSingleSignatureMsg = {
},
status: 'unapproved',
time: 1716826404122,
- type: 'eth_signTypedData',
+ type: TransactionType.signTypedData,
msgParams: {
data: '{"types":{"PermitSingle":[{"name":"details","type":"PermitDetails"},{"name":"spender","type":"address"},{"name":"sigDeadline","type":"uint256"}],"PermitDetails":[{"name":"token","type":"address"},{"name":"amount","type":"uint160"},{"name":"expiration","type":"uint48"},{"name":"nonce","type":"uint48"}],"EIP712Domain":[{"name":"name","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}]},"domain":{"name":"Permit2","chainId":"1","verifyingContract":"0x000000000022d473030f116ddee9f6b43ac78ba3"},"primaryType":"PermitSingle","message":{"details":{"token":"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","amount":"1461501637330902918203684832716283019655932542975","expiration":"1722887542","nonce":"5"},"spender":"0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad","sigDeadline":"1720297342"}}',
from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477',
version: 'V4',
+ requestId: 16,
signatureMethod: 'eth_signTypedData_v4',
origin: 'https://metamask.github.io',
},
diff --git a/test/e2e/tests/confirmations/signatures/permit.spec.ts b/test/e2e/tests/confirmations/signatures/permit.spec.ts
index a8191a15f229..6dadf732c246 100644
--- a/test/e2e/tests/confirmations/signatures/permit.spec.ts
+++ b/test/e2e/tests/confirmations/signatures/permit.spec.ts
@@ -123,7 +123,7 @@ async function assertInfoValues(driver: Driver) {
});
const value = driver.findElement({ text: '3,000' });
const nonce = driver.findElement({ text: '0' });
- const deadline = driver.findElement({ text: '02 August 1971, 16:53' });
+ const deadline = driver.findElement({ text: '09 June 3554, 16:53' });
assert.ok(await origin, 'origin');
assert.ok(await contractPetName, 'contractPetName');
diff --git a/ui/components/app/confirm/info/row/date.stories.tsx b/ui/components/app/confirm/info/row/date.stories.tsx
index 971ba7624f3e..e0e6a9a07dec 100644
--- a/ui/components/app/confirm/info/row/date.stories.tsx
+++ b/ui/components/app/confirm/info/row/date.stories.tsx
@@ -18,9 +18,9 @@ const ConfirmInfoRowDateStory = {
},
};
-export const DefaultStory = ({ date }) => ;
+export const DefaultStory = ({ date }) => ;
DefaultStory.args = {
- date: 1633019124000,
+ date: 1633019124,
};
export default ConfirmInfoRowDateStory;
diff --git a/ui/components/app/confirm/info/row/date.test.tsx b/ui/components/app/confirm/info/row/date.test.tsx
index eda8510e4e7c..8f6ac22f6c58 100644
--- a/ui/components/app/confirm/info/row/date.test.tsx
+++ b/ui/components/app/confirm/info/row/date.test.tsx
@@ -5,7 +5,9 @@ import { ConfirmInfoRowDate } from './date';
describe('ConfirmInfoRowDate', () => {
it('should match snapshot', () => {
- const { getByText } = render( );
+ const { getByText } = render(
+ ,
+ );
expect(getByText('30 September 2021, 16:25')).toBeInTheDocument();
});
});
diff --git a/ui/components/app/confirm/info/row/date.tsx b/ui/components/app/confirm/info/row/date.tsx
index 47fa8e4ea56a..278c1e514c2f 100644
--- a/ui/components/app/confirm/info/row/date.tsx
+++ b/ui/components/app/confirm/info/row/date.tsx
@@ -6,14 +6,17 @@ import {
FlexWrap,
TextColor,
} from '../../../../../helpers/constants/design-system';
-import { formatUTCDate } from '../../../../../helpers/utils/util';
+import { formatUTCDateFromUnixTimestamp } from '../../../../../helpers/utils/util';
import { Box, Text } from '../../../../component-library';
export type ConfirmInfoRowDateProps = {
- date: number;
+ /** timestamp as seconds since unix epoch e.g. Solidity block.timestamp (type uint256) value */
+ unixTimestamp: number;
};
-export const ConfirmInfoRowDate = ({ date }: ConfirmInfoRowDateProps) => (
+export const ConfirmInfoRowDate = ({
+ unixTimestamp,
+}: ConfirmInfoRowDateProps) => (
(
gap={2}
>
- {formatUTCDate(date)}
+ {formatUTCDateFromUnixTimestamp(unixTimestamp)}
);
diff --git a/ui/helpers/utils/util.js b/ui/helpers/utils/util.js
index 7eeab828a750..39c86e79bf75 100644
--- a/ui/helpers/utils/util.js
+++ b/ui/helpers/utils/util.js
@@ -39,13 +39,17 @@ export function formatDate(date, format = "M/d/y 'at' T") {
return DateTime.fromMillis(date).toFormat(format);
}
-export const formatUTCDate = (dateInMillis) => {
- if (!dateInMillis) {
- return dateInMillis;
+/**
+ * @param {number} unixTimestamp - timestamp as seconds since unix epoch
+ * @returns {string} formatted date string e.g. "14 July 2034, 22:22"
+ */
+export const formatUTCDateFromUnixTimestamp = (unixTimestamp) => {
+ if (!unixTimestamp) {
+ return unixTimestamp;
}
- return DateTime.fromMillis(dateInMillis)
- .setZone('utc')
+ return DateTime.fromSeconds(unixTimestamp)
+ .toUTC()
.toFormat('dd LLLL yyyy, HH:mm');
};
diff --git a/ui/helpers/utils/util.test.js b/ui/helpers/utils/util.test.js
index e9485a262197..e10c70630dba 100644
--- a/ui/helpers/utils/util.test.js
+++ b/ui/helpers/utils/util.test.js
@@ -1044,15 +1044,15 @@ describe('util', () => {
});
});
- describe('formatUTCDate', () => {
+ describe('formatUTCDateFromUnixTimestamp', () => {
it('formats passed date string', () => {
- expect(util.formatUTCDate(1633019124000)).toStrictEqual(
- '30 September 2021, 16:25',
+ expect(util.formatUTCDateFromUnixTimestamp(2036528542)).toStrictEqual(
+ '14 July 2034, 22:22',
);
});
it('returns empty string if empty string is passed', () => {
- expect(util.formatUTCDate('')).toStrictEqual('');
+ expect(util.formatUTCDateFromUnixTimestamp('')).toStrictEqual('');
});
});
diff --git a/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.tsx b/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.tsx
index 8c00c16f9c02..a4ba9fcbc95f 100644
--- a/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.tsx
+++ b/ui/pages/confirmations/components/confirm/info/personal-sign/siwe-sign/siwe-sign.tsx
@@ -66,7 +66,9 @@ const SIWESignInfo: React.FC = () => {
{requestId && (
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/__snapshots__/typed-sign.test.tsx.snap b/ui/pages/confirmations/components/confirm/info/typed-sign/__snapshots__/typed-sign.test.tsx.snap
index b9b75a2f4ee5..9e0218a9c9f5 100644
--- a/ui/pages/confirmations/components/confirm/info/typed-sign/__snapshots__/typed-sign.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/__snapshots__/typed-sign.test.tsx.snap
@@ -462,7 +462,594 @@ exports[`TypedSignInfo correctly renders permit sign type 1`] = `
class="mm-box mm-text mm-text--body-md mm-box--color-inherit"
style="white-space: pre-wrap;"
>
- 02 August 1971, 16:53
+ 09 June 3554, 16:53
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`TypedSignInfo correctly renders permit sign type with no deadline 1`] = `
+
+
+
+
+
+ Estimated changes
+
+
+
+
+
+ You're giving the spender permission to spend this many tokens from your account.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0xCcCCc...ccccC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0x5B38D...eddC4
+
+
+
+
+
+
+
+
+
+ metamask.github.io
+
+
+
+
+
+
+
+
+
+ 0xCcCCc...ccccC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0x935E7...05477
+
+
+
+
+
+
+
+
+
+
+ 0x5B38D...eddC4
+
+
+
+
+
+
+
diff --git a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx
index 1ac473dd40f8..089590d89618 100644
--- a/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx
+++ b/ui/pages/confirmations/components/confirm/info/typed-sign/typed-sign.test.tsx
@@ -5,6 +5,7 @@ import mockState from '../../../../../../../test/data/mock-state.json';
import { renderWithProvider } from '../../../../../../../test/lib/render-helpers';
import {
permitSignatureMsg,
+ permitSignatureMsgWithNoDeadline,
unapprovedTypedSignMsgV3,
unapprovedTypedSignMsgV4,
} from '../../../../../../../test/data/confirmations/typed_sign';
@@ -97,4 +98,20 @@ describe('TypedSignInfo', () => {
const { container } = renderWithProvider(
, mockStore);
expect(container).toMatchSnapshot();
});
+
+ it('correctly renders permit sign type with no deadline', () => {
+ const state = {
+ ...mockState,
+ metamask: {
+ ...mockState.metamask,
+ useTransactionSimulations: true,
+ },
+ confirm: {
+ currentConfirmation: permitSignatureMsgWithNoDeadline,
+ },
+ };
+ const mockStore = configureMockStore([])(state);
+ const { container } = renderWithProvider(
, mockStore);
+ expect(container).toMatchSnapshot();
+ });
});
diff --git a/ui/pages/confirmations/components/confirm/row/__snapshots__/dataTree.test.tsx.snap b/ui/pages/confirmations/components/confirm/row/__snapshots__/dataTree.test.tsx.snap
index 06a50c385aed..1c341b09e71d 100644
--- a/ui/pages/confirmations/components/confirm/row/__snapshots__/dataTree.test.tsx.snap
+++ b/ui/pages/confirmations/components/confirm/row/__snapshots__/dataTree.test.tsx.snap
@@ -802,3 +802,102 @@ exports[`DataTree should match snapshot for permit signature type 1`] = `
`;
+
+exports[`DataTree should match snapshot for permit signature type and deadline is -1 (None) 1`] = `
+
+`;
diff --git a/ui/pages/confirmations/components/confirm/row/dataTree.test.tsx b/ui/pages/confirmations/components/confirm/row/dataTree.test.tsx
index 699539d21a71..b427b6a8ee97 100644
--- a/ui/pages/confirmations/components/confirm/row/dataTree.test.tsx
+++ b/ui/pages/confirmations/components/confirm/row/dataTree.test.tsx
@@ -83,6 +83,19 @@ describe('DataTree', () => {
expect(container).toMatchSnapshot();
});
+ it('should match snapshot for permit signature type and deadline is -1 (None)', () => {
+ const mockPermitData = JSON.parse(
+ permitSignatureMsg.msgParams?.data as string,
+ );
+ mockPermitData.message.deadline = '-1';
+
+ const { container } = renderWithProvider(
+
,
+ store,
+ );
+ expect(container).toMatchSnapshot();
+ });
+
it('should match snapshot for order signature type', () => {
const { container } = renderWithProvider(
= {
[Field.Deadline]: [...PRIMARY_TYPES_PERMIT],
[Field.EndTime]: [...PRIMARY_TYPES_ORDER],
[Field.Expiration]: [PrimaryType.PermitBatch, PrimaryType.PermitSingle],
+ [Field.Expiry]: [...PRIMARY_TYPES_PERMIT],
[Field.SigDeadline]: [...PRIMARY_TYPES_PERMIT],
[Field.StartTime]: [...PRIMARY_TYPES_ORDER],
[Field.ValidTo]: [...PRIMARY_TYPES_ORDER],
};
+/**
+ * Date values may include -1 to represent a null value
+ * e.g.
+ * {@see {@link https://eips.ethereum.org/EIPS/eip-2612}}
+ * "The deadline argument can be set to uint(-1) to create Permits that effectively never expire."
+ */
+const NONE_DATE_VALUE = -1;
+
const getTokenDecimalsOfDataTree = async (
dataTreeData: Record | TreeData[],
): Promise => {
@@ -146,6 +157,8 @@ const DataField = memo(
value: ValueType;
tokenDecimals: number;
}) => {
+ const t = useI18nContext();
+
if (typeof value === 'object' && value !== null) {
return (
;
+ if (isDateField(label, primaryType) && Boolean(value)) {
+ const intValue = parseInt(value, 10);
+
+ return intValue === NONE_DATE_VALUE ? (
+
+ ) : (
+
+ );
}
if (isTokenUnitsField(label, primaryType)) {
diff --git a/ui/pages/confirmations/confirm/__snapshots__/confirm.test.tsx.snap b/ui/pages/confirmations/confirm/__snapshots__/confirm.test.tsx.snap
index 84bab3847b1e..cc1007342e1a 100644
--- a/ui/pages/confirmations/confirm/__snapshots__/confirm.test.tsx.snap
+++ b/ui/pages/confirmations/confirm/__snapshots__/confirm.test.tsx.snap
@@ -921,7 +921,7 @@ exports[`Confirm should match snapshot for signature - typed sign - V4 - PermitB
class="mm-box mm-text mm-text--body-md mm-box--color-inherit"
style="white-space: pre-wrap;"
>
- 20 January 1970, 22:34
+ 05 August 2024, 19:52
@@ -1095,7 +1095,7 @@ exports[`Confirm should match snapshot for signature - typed sign - V4 - PermitB
class="mm-box mm-text mm-text--body-md mm-box--color-inherit"
style="white-space: pre-wrap;"
>
- 20 January 1970, 22:34
+ 05 August 2024, 19:54
@@ -1218,7 +1218,7 @@ exports[`Confirm should match snapshot for signature - typed sign - V4 - PermitB
class="mm-box mm-text mm-text--body-md mm-box--color-inherit"
style="white-space: pre-wrap;"
>
- 20 January 1970, 21:51
+ 06 July 2024, 20:22
@@ -1880,7 +1880,7 @@ exports[`Confirm should match snapshot for signature - typed sign - V4 - PermitS
class="mm-box mm-text mm-text--body-md mm-box--color-inherit"
style="white-space: pre-wrap;"
>
- 20 January 1970, 22:34
+ 05 August 2024, 19:52
@@ -2001,7 +2001,7 @@ exports[`Confirm should match snapshot for signature - typed sign - V4 - PermitS
class="mm-box mm-text mm-text--body-md mm-box--color-inherit"
style="white-space: pre-wrap;"
>
- 20 January 1970, 21:51
+ 06 July 2024, 20:22
@@ -3252,7 +3252,7 @@ exports[`Confirm should match snapshot for signature - typed sign - permit 1`] =
class="mm-box mm-text mm-text--body-md mm-box--color-inherit"
style="white-space: pre-wrap;"
>
- 02 August 1971, 16:53
+ 09 June 3554, 16:53
From 080fd236c41d3b552085132971314a0975b0f6e1 Mon Sep 17 00:00:00 2001
From: OGPoyraz
Date: Mon, 23 Sep 2024 22:02:02 +0200
Subject: [PATCH 36/43] fix: cherry pick ledger confirm button fix into
`12.3.0` (#27342)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
This PR cherry-picks
https://github.com/MetaMask/metamask-extension/pull/27331
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27342?quickstart=1)
## **Related issues**
https://github.com/MetaMask/metamask-extension/pull/27331
## **Manual testing steps**
Tested and approved by QA in original PR
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
ui/pages/confirmations/hooks/useLedgerConnection.ts | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/ui/pages/confirmations/hooks/useLedgerConnection.ts b/ui/pages/confirmations/hooks/useLedgerConnection.ts
index c9bd26fef3c8..2774844262f4 100644
--- a/ui/pages/confirmations/hooks/useLedgerConnection.ts
+++ b/ui/pages/confirmations/hooks/useLedgerConnection.ts
@@ -1,5 +1,6 @@
import { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
+import { TransactionMeta } from '@metamask/transaction-controller';
import {
HardwareTransportStates,
LEDGER_USB_VENDOR_ID,
@@ -24,16 +25,13 @@ const useLedgerConnection = () => {
const dispatch = useDispatch();
const currentConfirmation = useSelector(
currentConfirmationSelector,
- ) as SignatureRequestType;
+ ) as SignatureRequestType & TransactionMeta;
const ledgerTransportType = useSelector(getLedgerTransportType);
const transportStatus = useSelector(getLedgerTransportStatus);
const webHidConnectedStatus = useSelector(getLedgerWebHidConnectedStatus);
- let from: string | undefined;
- // todo: extend to other confirmation types
- if (currentConfirmation?.msgParams) {
- from = currentConfirmation.msgParams.from;
- }
+ const from =
+ currentConfirmation?.msgParams?.from ?? currentConfirmation?.txParams?.from;
const isLedgerWallet = useSelector(
(state) => from && isAddressLedger(state, from),
From 24b5e1e297bf133d37cdc2c771005eb671285d4a Mon Sep 17 00:00:00 2001
From: Vinicius Stevam <45455812+vinistevam@users.noreply.github.com>
Date: Tue, 24 Sep 2024 12:55:30 +0100
Subject: [PATCH 37/43] fix: cherry pick disable the confirm button when there
is a blocking alert fix into 12.3.0 (#27354)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
This PR cherry-picks
https://github.com/MetaMask/metamask-extension/pull/27347
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27354?quickstart=1)
## **Related issues**
Fixes: https://github.com/MetaMask/metamask-extension/issues/27147
## **Manual testing steps**
Tested and approved by QA in original PR
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
.../alerts/insufficient-funds.spec.ts | 85 +++++++++++++++++++
.../alert-system/alert-modal/alert-modal.tsx | 7 +-
.../components/confirm/footer/footer.test.tsx | 37 ++++++--
.../components/confirm/footer/footer.tsx | 36 +++++++-
4 files changed, 157 insertions(+), 8 deletions(-)
create mode 100644 test/e2e/tests/confirmations/alerts/insufficient-funds.spec.ts
diff --git a/test/e2e/tests/confirmations/alerts/insufficient-funds.spec.ts b/test/e2e/tests/confirmations/alerts/insufficient-funds.spec.ts
new file mode 100644
index 000000000000..e600ed920c9b
--- /dev/null
+++ b/test/e2e/tests/confirmations/alerts/insufficient-funds.spec.ts
@@ -0,0 +1,85 @@
+import { strict as assert } from 'assert';
+import FixtureBuilder from '../../../fixture-builder';
+import {
+ PRIVATE_KEY,
+ convertETHToHexGwei,
+ withFixtures,
+ WINDOW_TITLES,
+} from '../../../helpers';
+import { SMART_CONTRACTS } from '../../../seeder/smart-contracts';
+import {
+ TestSuiteArguments,
+ openDAppWithContract,
+} from '../transactions/shared';
+import { Driver } from '../../../webdriver/driver';
+
+describe('Alert for insufficient funds @no-mmi', function () {
+ it('Shows an alert when the user tries to send a transaction with insufficient funds', async function () {
+ const nftSmartContract = SMART_CONTRACTS.NFTS;
+ const ganacheOptions = {
+ accounts: [
+ {
+ secretKey: PRIVATE_KEY,
+ balance: convertETHToHexGwei(0.0053), // Low balance only to create the contract and then trigger the alert for insufficient funds
+ },
+ ],
+ };
+ await withFixtures(
+ {
+ dapp: true,
+ fixtures: new FixtureBuilder()
+ .withPermissionControllerConnectedToTestDapp()
+ .withPreferencesController({
+ preferences: {
+ redesignedConfirmationsEnabled: true,
+ isRedesignedConfirmationsDeveloperEnabled: true,
+ },
+ })
+ .build(),
+ ganacheOptions,
+ smartContract: nftSmartContract,
+ title: this.test?.fullTitle(),
+ },
+ async ({ driver, contractRegistry }: TestSuiteArguments) => {
+ await openDAppWithContract(driver, contractRegistry, nftSmartContract);
+
+ await mintNft(driver);
+
+ await verifyAlertForInsufficientBalance(driver);
+
+ await verifyConfirmationIsDisabled(driver);
+ },
+ );
+ });
+});
+
+async function verifyConfirmationIsDisabled(driver: Driver) {
+ const confirmButton = await driver.findElement(
+ '[data-testid="confirm-footer-button"]',
+ );
+ assert.equal(await confirmButton.isEnabled(), false);
+}
+
+async function verifyAlertForInsufficientBalance(driver: Driver) {
+ const alert = await driver.findElement('[data-testid="inline-alert"]');
+ assert.equal(await alert.getText(), 'Alert');
+ await driver.clickElementSafe('.confirm-scroll-to-bottom__button');
+ await driver.clickElement('[data-testid="inline-alert"]');
+
+ const alertDescription = await driver.findElement(
+ '[data-testid="alert-modal__selected-alert"]',
+ );
+ const alertDescriptionText = await alertDescription.getText();
+ assert.equal(
+ alertDescriptionText,
+ 'You do not have enough ETH in your account to pay for transaction fees.',
+ );
+}
+
+async function mintNft(driver: Driver) {
+ await driver.switchToWindowWithTitle(WINDOW_TITLES.TestDApp);
+ await driver.clickElement(`#mintButton`);
+
+ await driver.waitUntilXWindowHandles(3);
+ await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
+}
diff --git a/ui/components/app/alert-system/alert-modal/alert-modal.tsx b/ui/components/app/alert-system/alert-modal/alert-modal.tsx
index 2d4ec4bb112c..fa31cb018091 100644
--- a/ui/components/app/alert-system/alert-modal/alert-modal.tsx
+++ b/ui/components/app/alert-system/alert-modal/alert-modal.tsx
@@ -166,7 +166,12 @@ function AlertDetails({
>
{customDetails ?? (
- {selectedAlert.message}
+
+ {selectedAlert.message}
+
{selectedAlert.alertDetails?.length ? (
{t('alertModalDetails')}
diff --git a/ui/pages/confirmations/components/confirm/footer/footer.test.tsx b/ui/pages/confirmations/components/confirm/footer/footer.test.tsx
index 9fd033fb90ff..5fb6b7e5ac76 100644
--- a/ui/pages/confirmations/components/confirm/footer/footer.test.tsx
+++ b/ui/pages/confirmations/components/confirm/footer/footer.test.tsx
@@ -12,6 +12,8 @@ import * as MMIConfirmations from '../../../../../hooks/useMMIConfirmations';
import * as Actions from '../../../../../store/actions';
import configureStore from '../../../../../store/store';
import { Severity } from '../../../../../helpers/constants/design-system';
+
+import { Alert } from '../../../../../ducks/confirm-alerts/confirm-alerts';
import Footer from './footer';
jest.mock('react-redux', () => ({
@@ -184,7 +186,8 @@ describe('ConfirmFooter', () => {
const OWNER_ID_MOCK = '123';
const KEY_ALERT_KEY_MOCK = 'Key';
const ALERT_MESSAGE_MOCK = 'Alert 1';
- const alertsMock = [
+
+ const alertsMock: Alert[] = [
{
key: KEY_ALERT_KEY_MOCK,
field: KEY_ALERT_KEY_MOCK,
@@ -213,12 +216,31 @@ describe('ConfirmFooter', () => {
};
it('renders the review alerts button when there are unconfirmed alerts', () => {
const { getByText } = render(stateWithAlertsMock);
- expect(getByText('Confirm')).toBeInTheDocument();
+ expect(getByText('Review alerts')).toBeInTheDocument();
});
- it('renders the confirm button when there are no unconfirmed alerts', () => {
- const { getByText } = render();
- expect(getByText('Confirm')).toBeInTheDocument();
+ it('renders the "review alerts" button disabled when there are blocking alerts', () => {
+ const stateWithMultipleDangerAlerts = {
+ ...stateWithAlertsMock,
+ confirmAlerts: {
+ alerts: {
+ [OWNER_ID_MOCK]: [
+ alertsMock[0],
+ {
+ ...alertsMock[0],
+ key: 'From',
+ isBlocking: true,
+ },
+ ],
+ },
+ confirmed: {
+ [OWNER_ID_MOCK]: { [KEY_ALERT_KEY_MOCK]: false },
+ },
+ },
+ };
+ const { getByText } = render(stateWithMultipleDangerAlerts);
+ expect(getByText('Review alerts')).toBeInTheDocument();
+ expect(getByText('Review alerts')).toBeDisabled();
});
it('sets the alert modal visible when the review alerts button is clicked', () => {
@@ -226,5 +248,10 @@ describe('ConfirmFooter', () => {
fireEvent.click(getByTestId('confirm-footer-button'));
expect(getByTestId('confirm-alert-modal-submit-button')).toBeDefined();
});
+
+ it('renders the "confirm" button when there are no alerts', () => {
+ const { getByText } = render();
+ expect(getByText('Confirm')).toBeInTheDocument();
+ });
});
});
diff --git a/ui/pages/confirmations/components/confirm/footer/footer.tsx b/ui/pages/confirmations/components/confirm/footer/footer.tsx
index a3d3e1bbc71d..7c36c31c164e 100644
--- a/ui/pages/confirmations/components/confirm/footer/footer.tsx
+++ b/ui/pages/confirmations/components/confirm/footer/footer.tsx
@@ -27,6 +27,30 @@ import {
import { confirmSelector } from '../../../selectors';
import { REDESIGN_TRANSACTION_TYPES } from '../../../utils';
import { getConfirmationSender } from '../utils';
+import { MetaMetricsEventLocation } from '../../../../../../shared/constants/metametrics';
+import { Severity } from '../../../../../helpers/constants/design-system';
+
+export type OnCancelHandler = ({
+ location,
+}: {
+ location: MetaMetricsEventLocation;
+}) => void;
+
+function getButtonDisabledState(
+ hasUnconfirmedDangerAlerts: boolean,
+ hasBlockingAlerts: boolean,
+ disabled: boolean,
+) {
+ if (hasBlockingAlerts) {
+ return true;
+ }
+
+ if (hasUnconfirmedDangerAlerts) {
+ return false;
+ }
+
+ return disabled;
+}
const ConfirmButton = ({
alertOwnerId = '',
@@ -47,6 +71,10 @@ const ConfirmButton = ({
const { dangerAlerts, hasDangerAlerts, hasUnconfirmedDangerAlerts } =
useAlerts(alertOwnerId);
+ const hasDangerBlockingAlerts = dangerAlerts.some(
+ (alert) => alert.severity === Severity.Danger && alert.isBlocking,
+ );
+
const handleCloseConfirmModal = useCallback(() => {
setConfirmModalVisible(false);
}, []);
@@ -70,12 +98,16 @@ const ConfirmButton = ({
block
danger
data-testid="confirm-footer-button"
- disabled={hasUnconfirmedDangerAlerts ? false : disabled}
+ disabled={getButtonDisabledState(
+ hasUnconfirmedDangerAlerts,
+ hasDangerBlockingAlerts,
+ disabled,
+ )}
onClick={handleOpenConfirmModal}
size={ButtonSize.Lg}
startIconName={IconName.Danger}
>
- {dangerAlerts?.length > 1 ? t('reviewAlerts') : t('confirm')}
+ {dangerAlerts?.length > 0 ? t('reviewAlerts') : t('confirm')}
) : (
Date: Tue, 24 Sep 2024 22:04:35 +0530
Subject: [PATCH 38/43] cherry-pick: Update package @blockaid/ppom_release to
version 1.5.3 (#27372)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Update package @blockaid/ppom_release to version 1.5.3
## **Related issues**
Fixes: https://github.com/MetaMask/MetaMask-planning/issues/3274
## **Manual testing steps**
NA
## **Screenshots/Recordings**
NA
## **Pre-merge author checklist**
- [X] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [X] I've completed the PR template to the best of my ability
- [X] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [X] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
package.json | 2 +-
.../__snapshots__/blockaid-banner-alert.test.js.snap | 12 ++++++------
yarn.lock | 10 +++++-----
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/package.json b/package.json
index 40b383e90794..c2cd9277ec71 100644
--- a/package.json
+++ b/package.json
@@ -270,7 +270,7 @@
},
"dependencies": {
"@babel/runtime": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch",
- "@blockaid/ppom_release": "^1.5.2",
+ "@blockaid/ppom_release": "^1.5.3",
"@contentful/rich-text-html-renderer": "^16.3.5",
"@ensdomains/content-hash": "^2.5.7",
"@ethereumjs/tx": "^4.1.1",
diff --git a/ui/pages/confirmations/components/security-provider-banner-alert/blockaid-banner-alert/__snapshots__/blockaid-banner-alert.test.js.snap b/ui/pages/confirmations/components/security-provider-banner-alert/blockaid-banner-alert/__snapshots__/blockaid-banner-alert.test.js.snap
index 127e733ad95d..af7e4e9e05dd 100644
--- a/ui/pages/confirmations/components/security-provider-banner-alert/blockaid-banner-alert/__snapshots__/blockaid-banner-alert.test.js.snap
+++ b/ui/pages/confirmations/components/security-provider-banner-alert/blockaid-banner-alert/__snapshots__/blockaid-banner-alert.test.js.snap
@@ -54,7 +54,7 @@ exports[`Blockaid Banner Alert should render 'danger' UI when securityAlertRespo
Something doesn't look right?
@@ -151,7 +151,7 @@ exports[`Blockaid Banner Alert should render 'warning' UI when securityAlertResp
Something doesn't look right?
@@ -248,7 +248,7 @@ exports[`Blockaid Banner Alert should render 'warning' UI when securityAlertResp
Something doesn't look right?
@@ -346,7 +346,7 @@ exports[`Blockaid Banner Alert should render details section even when features
Something doesn't look right?
@@ -457,7 +457,7 @@ exports[`Blockaid Banner Alert should render details when provided 1`] = `
Something doesn't look right?
@@ -556,7 +556,7 @@ exports[`Blockaid Banner Alert should render link to report url 1`] = `
Something doesn't look right?
diff --git a/yarn.lock b/yarn.lock
index d0a172e1d380..00064b56dea0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1701,10 +1701,10 @@ __metadata:
languageName: node
linkType: hard
-"@blockaid/ppom_release@npm:^1.5.2":
- version: 1.5.2
- resolution: "@blockaid/ppom_release@npm:1.5.2"
- checksum: 10/b47af74e8a315d996abb8371a7b28f9923bf78272cc408b2307024e2050b57f36c53b6b9a57b276b0910b449ebb384897e293abad356131ccf65c6c3c5ca31ae
+"@blockaid/ppom_release@npm:^1.5.3":
+ version: 1.5.3
+ resolution: "@blockaid/ppom_release@npm:1.5.3"
+ checksum: 10/3e8a16866b477eef247c4a65c80d361e7429389e7e760c0497bc69269526e2325fa15cdbf93455c1655877a7760c6b4fc9ce87d80f0290483160632300bcfbc8
languageName: node
linkType: hard
@@ -25895,7 +25895,7 @@ __metadata:
"@babel/preset-typescript": "npm:^7.23.2"
"@babel/register": "npm:^7.22.15"
"@babel/runtime": "patch:@babel/runtime@npm%3A7.24.0#~/.yarn/patches/@babel-runtime-npm-7.24.0-7eb1dd11a2.patch"
- "@blockaid/ppom_release": "npm:^1.5.2"
+ "@blockaid/ppom_release": "npm:^1.5.3"
"@contentful/rich-text-html-renderer": "npm:^16.3.5"
"@ensdomains/content-hash": "npm:^2.5.7"
"@ethereumjs/tx": "npm:^4.1.1"
From 24f982873b8dd5579851a6f2987ef1981c863466 Mon Sep 17 00:00:00 2001
From: Maarten Zuidhoorn
Date: Tue, 24 Sep 2024 20:33:32 +0200
Subject: [PATCH 39/43] fix: Don't show third party notice for preinstalled
Snaps (#27365)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This cherry-picks commit 5cc14af into release 12.3.0.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27319?quickstart=1)
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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.
---
.../snaps/snaps-connect/snaps-connect.js | 28 ++++++++++++-------
ui/selectors/selectors.js | 12 ++++++++
2 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/ui/pages/permissions-connect/snaps/snaps-connect/snaps-connect.js b/ui/pages/permissions-connect/snaps/snaps-connect/snaps-connect.js
index 0ef95da18f89..fe45b7d02ef0 100644
--- a/ui/pages/permissions-connect/snaps/snaps-connect/snaps-connect.js
+++ b/ui/pages/permissions-connect/snaps/snaps-connect/snaps-connect.js
@@ -20,8 +20,12 @@ import SnapConnectCell from '../../../../components/app/snaps/snap-connect-cell/
import { getDedupedSnaps } from '../../../../helpers/utils/util';
import PulseLoader from '../../../../components/ui/pulse-loader/pulse-loader';
import SnapPrivacyWarning from '../../../../components/app/snaps/snap-privacy-warning/snap-privacy-warning';
-import { getPermissions, getSnapMetadata } from '../../../../selectors';
import SnapAvatar from '../../../../components/app/snaps/snap-avatar/snap-avatar';
+import {
+ getPermissions,
+ getPreinstalledSnaps,
+ getSnapMetadata,
+} from '../../../../selectors';
import { useOriginMetadata } from '../../../../hooks/useOriginMetadata';
export default function SnapsConnect({
@@ -35,12 +39,23 @@ export default function SnapsConnect({
const t = useI18nContext();
const { origin } = targetSubjectMetadata;
const [isLoading, setIsLoading] = useState(false);
- const [isShowingSnapsPrivacyWarning, setIsShowingSnapsPrivacyWarning] =
- useState(!snapsInstallPrivacyWarningShown);
+
const currentPermissions = useSelector((state) =>
getPermissions(state, request?.metadata?.origin),
);
+ const preinstalledSnaps = useSelector(getPreinstalledSnaps);
+
+ const snaps = getDedupedSnaps(request, currentPermissions);
+ const snapId = snaps[0];
+ const { name: snapName } = useSelector((state) =>
+ getSnapMetadata(state, snapId),
+ );
+
+ const isPreinstalled = Object.keys(preinstalledSnaps).includes(snapId);
+ const [isShowingSnapsPrivacyWarning, setIsShowingSnapsPrivacyWarning] =
+ useState(!isPreinstalled && !snapsInstallPrivacyWarningShown);
+
const onCancel = useCallback(() => {
rejectConnection(request.metadata.id);
}, [request, rejectConnection]);
@@ -54,16 +69,9 @@ export default function SnapsConnect({
}
}, [request, approveConnection]);
- const snaps = getDedupedSnaps(request, currentPermissions);
-
const SnapsConnectContent = () => {
const { hostname: trimmedOrigin } = useOriginMetadata(origin) || {};
- const snapId = snaps[0];
- const { name: snapName } = useSelector((state) =>
- getSnapMetadata(state, snapId),
- );
-
if (isLoading) {
return (
{
}, {});
});
+export const getPreinstalledSnaps = createDeepEqualSelector(
+ getSnaps,
+ (snaps) => {
+ return Object.values(snaps).reduce((acc, snap) => {
+ if (snap.preinstalled) {
+ acc[snap.id] = snap;
+ }
+ return acc;
+ }, {});
+ },
+);
+
export const getInsightSnaps = createDeepEqualSelector(
getEnabledSnaps,
getPermissionSubjects,
From 1c3f435effcba9e07a72cb57d6caa03bbc47f2d3 Mon Sep 17 00:00:00 2001
From: Matthew Walsh
Date: Wed, 25 Sep 2024 13:38:24 +0100
Subject: [PATCH 40/43] fix (cherry-pick): incorrect method name parsed from
transaction data (#27363) (#27379)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## **Description**
Cherry pick of #27363 for version 12.3.0.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27379?quickstart=1)
## **Related issues**
## **Manual testing steps**
## **Screenshots/Recordings**
### **Before**
### **After**
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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/scripts/lib/util.test.js | 24 +++++-
app/scripts/lib/util.ts | 2 +-
shared/lib/four-byte.test.ts | 19 +++++
shared/lib/four-byte.ts | 12 ++-
shared/modules/transaction.utils.test.js | 17 ++++
shared/modules/transaction.utils.ts | 7 ++
.../confirm-hexdata/confirm-hexdata.js | 3 +-
.../confirm-hexdata/confirm-hexdata.test.js | 33 ++++----
.../hooks/useDecodedTransactionData.test.ts | 28 ++++---
.../info/hooks/useDecodedTransactionData.ts | 3 +-
.../confirm/info/hooks/useFourByte.test.ts | 4 +-
.../useKnownMethodDataInTransaction.test.ts | 80 -------------------
.../hooks/useKnownMethodDataInTransaction.ts | 21 -----
.../transaction-data/transaction-data.tsx | 3 +-
.../confirm-transaction-base.component.js | 3 +-
.../token-allowance/token-allowance.js | 4 +-
ui/selectors/selectors.js | 15 +++-
17 files changed, 136 insertions(+), 142 deletions(-)
delete mode 100644 ui/pages/confirmations/components/confirm/info/hooks/useKnownMethodDataInTransaction.test.ts
delete mode 100644 ui/pages/confirmations/components/confirm/info/hooks/useKnownMethodDataInTransaction.ts
diff --git a/app/scripts/lib/util.test.js b/app/scripts/lib/util.test.js
index d428c3cd7ae1..7ae7e7b36a88 100644
--- a/app/scripts/lib/util.test.js
+++ b/app/scripts/lib/util.test.js
@@ -369,21 +369,25 @@ describe('app utils', () => {
name: 'Approve Tokens',
},
};
+
it('return null if use4ByteResolution is not true', async () => {
expect(
await getMethodDataName(knownMethodData, false, '0x60806040'),
).toStrictEqual(null);
});
+
it('return null if prefixedData is not defined', async () => {
expect(
await getMethodDataName(knownMethodData, true, undefined),
).toStrictEqual(null);
});
+
it('return details from knownMethodData if defined', async () => {
expect(
await getMethodDataName(knownMethodData, true, '0x60806040'),
).toStrictEqual(knownMethodData['0x60806040']);
});
+
it('invoke getMethodDataAsync if details not available in knownMethodData', async () => {
const DUMMY_METHOD_NAME = {
name: 'Dummy Method Name',
@@ -392,9 +396,10 @@ describe('app utils', () => {
.spyOn(FourBiteUtils, 'getMethodDataAsync')
.mockResolvedValue(DUMMY_METHOD_NAME);
expect(
- await getMethodDataName(knownMethodData, true, '0x123'),
+ await getMethodDataName(knownMethodData, true, '0x123', jest.fn()),
).toStrictEqual(DUMMY_METHOD_NAME);
});
+
it('invoke addKnownMethodData if details not available in knownMethodData', async () => {
const DUMMY_METHOD_NAME = {
name: 'Dummy Method Name',
@@ -413,5 +418,22 @@ describe('app utils', () => {
).toStrictEqual(DUMMY_METHOD_NAME);
expect(addKnownMethodData).toHaveBeenCalledTimes(1);
});
+
+ it('does not invoke addKnownMethodData if no method data available', async () => {
+ const addKnownMethodData = jest.fn();
+
+ jest.spyOn(FourBiteUtils, 'getMethodDataAsync').mockResolvedValue({});
+
+ expect(
+ await getMethodDataName(
+ knownMethodData,
+ true,
+ '0x123',
+ addKnownMethodData,
+ ),
+ ).toStrictEqual({});
+
+ expect(addKnownMethodData).toHaveBeenCalledTimes(0);
+ });
});
});
diff --git a/app/scripts/lib/util.ts b/app/scripts/lib/util.ts
index 2caade79b83e..e41b2a00b670 100644
--- a/app/scripts/lib/util.ts
+++ b/app/scripts/lib/util.ts
@@ -411,7 +411,7 @@ export const getMethodDataName = async (
provider,
);
- if (addKnownMethodData) {
+ if (methodData?.name) {
addKnownMethodData(fourBytePrefix, methodData as MethodData);
}
diff --git a/shared/lib/four-byte.test.ts b/shared/lib/four-byte.test.ts
index e25235e6ae54..2867aa2e51b7 100644
--- a/shared/lib/four-byte.test.ts
+++ b/shared/lib/four-byte.test.ts
@@ -25,6 +25,25 @@ describe('Four Byte', () => {
expect(result).toStrictEqual('someOtherFunction(address,uint256)');
});
+
+ // @ts-expect-error This is missing from the Mocha type definitions
+ it.each([undefined, null, '', '0x', '0X'])(
+ 'returns undefined if four byte prefix is %s',
+ async (prefix: string) => {
+ expect(await getMethodFrom4Byte(prefix)).toBeUndefined();
+ },
+ );
+
+ // @ts-expect-error This is missing from the Mocha type definitions
+ it.each([
+ ['with hex prefix', '0x1234567'],
+ ['without hex prefix', '1234567'],
+ ])(
+ 'returns undefined if length of four byte prefix %s is less than 8',
+ async (_: string, prefix: string) => {
+ expect(await getMethodFrom4Byte(prefix)).toBeUndefined();
+ },
+ );
});
describe('getMethodDataAsync', () => {
diff --git a/shared/lib/four-byte.ts b/shared/lib/four-byte.ts
index 167dfc563b73..05c91af9c768 100644
--- a/shared/lib/four-byte.ts
+++ b/shared/lib/four-byte.ts
@@ -1,4 +1,7 @@
import { MethodRegistry } from 'eth-method-registry';
+import { Hex } from '@metamask/utils';
+import { hasTransactionData } from '../modules/transaction.utils';
+import { stripHexPrefix } from '../modules/hexstring-utils';
import fetchWithCache from './fetch-with-cache';
type FourByteResult = {
@@ -12,7 +15,14 @@ type FourByteResponse = {
export async function getMethodFrom4Byte(
fourBytePrefix: string,
-): Promise {
+): Promise {
+ if (
+ !hasTransactionData(fourBytePrefix as Hex) ||
+ stripHexPrefix(fourBytePrefix)?.length < 8
+ ) {
+ return undefined;
+ }
+
const fourByteResponse = (await fetchWithCache({
url: `https://www.4byte.directory/api/v1/signatures/?hex_signature=${fourBytePrefix}`,
fetchOptions: {
diff --git a/shared/modules/transaction.utils.test.js b/shared/modules/transaction.utils.test.js
index 133f2de9141e..28bfaaa34ed7 100644
--- a/shared/modules/transaction.utils.test.js
+++ b/shared/modules/transaction.utils.test.js
@@ -4,6 +4,7 @@ import { TransactionType } from '@metamask/transaction-controller';
import { createTestProviderTools } from '../../test/stub/provider';
import {
determineTransactionType,
+ hasTransactionData,
isEIP1559Transaction,
isLegacyTransaction,
parseStandardTokenTransactionData,
@@ -417,4 +418,20 @@ describe('Transaction.utils', function () {
});
});
});
+
+ describe('hasTransactionData', () => {
+ it.each([
+ ['has prefix', '0x1234'],
+ ['has no prefix', '1234'],
+ ])('returns true if data %s', (_, data) => {
+ expect(hasTransactionData(data)).toBe(true);
+ });
+
+ it.each([undefined, null, '', '0x', '0X'])(
+ 'returns false if data is %s',
+ (data) => {
+ expect(hasTransactionData(data)).toBe(false);
+ },
+ );
+ });
});
diff --git a/shared/modules/transaction.utils.ts b/shared/modules/transaction.utils.ts
index e09680c6c4bd..910fe9b6d4be 100644
--- a/shared/modules/transaction.utils.ts
+++ b/shared/modules/transaction.utils.ts
@@ -14,6 +14,7 @@ import {
} from '@metamask/transaction-controller';
import type { TransactionParams } from '@metamask/transaction-controller';
+import { Hex } from '@metamask/utils';
import { AssetType, TokenStandard } from '../constants/transaction';
import { readAddressAsContract } from './contract-utils';
import { isEqualCaseInsensitive } from './string-utils';
@@ -319,3 +320,9 @@ export const parseTypedDataMessage = (dataToParse: string) => {
return result;
};
+
+export function hasTransactionData(transactionData?: Hex): boolean {
+ return Boolean(
+ transactionData?.length && transactionData?.toLowerCase?.() !== '0x',
+ );
+}
diff --git a/ui/pages/confirmations/components/confirm-hexdata/confirm-hexdata.js b/ui/pages/confirmations/components/confirm-hexdata/confirm-hexdata.js
index 1309d7e7e618..8108cac67a0b 100644
--- a/ui/pages/confirmations/components/confirm-hexdata/confirm-hexdata.js
+++ b/ui/pages/confirmations/components/confirm-hexdata/confirm-hexdata.js
@@ -15,6 +15,7 @@ import {
import Box from '../../../../components/ui/box';
import { Text } from '../../../../components/component-library';
import CopyRawData from '../transaction-decoding/components/ui/copy-raw-data';
+import { hasTransactionData } from '../../../../../shared/modules/transaction.utils';
const ConfirmHexData = ({ txData, dataHexComponent }) => {
const t = useI18nContext();
@@ -28,7 +29,7 @@ const ConfirmHexData = ({ txData, dataHexComponent }) => {
return dataHexComponent;
}
- if (!txParams.data || !txParams.to) {
+ if (!hasTransactionData(txParams.data) || !txParams.to) {
return null;
}
diff --git a/ui/pages/confirmations/components/confirm-hexdata/confirm-hexdata.test.js b/ui/pages/confirmations/components/confirm-hexdata/confirm-hexdata.test.js
index f9f41566c4c0..d31478775ba2 100644
--- a/ui/pages/confirmations/components/confirm-hexdata/confirm-hexdata.test.js
+++ b/ui/pages/confirmations/components/confirm-hexdata/confirm-hexdata.test.js
@@ -28,21 +28,24 @@ describe('ConfirmHexData', () => {
expect(await findByText('Transfer')).toBeInTheDocument();
});
- it('should return null if transaction has no data', () => {
- const { container } = renderWithProvider(
- ,
- store,
- );
- expect(container.firstChild).toStrictEqual(null);
- });
+ it.each([undefined, null, '', '0x', '0X'])(
+ 'should return null if transaction data is %s',
+ (data) => {
+ const { container } = renderWithProvider(
+ ,
+ store,
+ );
+ expect(container.firstChild).toStrictEqual(null);
+ },
+ );
it('should return null if transaction has no to address', () => {
const { container } = renderWithProvider(
diff --git a/ui/pages/confirmations/components/confirm/info/hooks/useDecodedTransactionData.test.ts b/ui/pages/confirmations/components/confirm/info/hooks/useDecodedTransactionData.test.ts
index 5c185d98c282..c070e1ae0635 100644
--- a/ui/pages/confirmations/components/confirm/info/hooks/useDecodedTransactionData.test.ts
+++ b/ui/pages/confirmations/components/confirm/info/hooks/useDecodedTransactionData.test.ts
@@ -47,19 +47,23 @@ async function runHook(stateOptions?: Parameters[0]) {
describe('useDecodedTransactionData', () => {
const decodeTransactionDataMock = jest.mocked(decodeTransactionData);
- it('returns undefined if no transaction data', async () => {
- const result = await runHook({
- currentConfirmation: {
- chainId: CHAIN_ID_MOCK,
- txParams: {
- data: '',
- to: CONTRACT_ADDRESS_MOCK,
- } as TransactionParams,
- },
- });
+ // @ts-expect-error This is missing from the Mocha type definitions
+ it.each([undefined, null, '', '0x', '0X'])(
+ 'returns undefined if transaction data is %s',
+ async () => {
+ const result = await runHook({
+ currentConfirmation: {
+ chainId: CHAIN_ID_MOCK,
+ txParams: {
+ data: '',
+ to: CONTRACT_ADDRESS_MOCK,
+ } as TransactionParams,
+ },
+ });
- expect(result).toStrictEqual({ pending: false, value: undefined });
- });
+ expect(result).toStrictEqual({ pending: false, value: undefined });
+ },
+ );
it('returns the decoded data', async () => {
decodeTransactionDataMock.mockResolvedValue(TRANSACTION_DECODE_SOURCIFY);
diff --git a/ui/pages/confirmations/components/confirm/info/hooks/useDecodedTransactionData.ts b/ui/pages/confirmations/components/confirm/info/hooks/useDecodedTransactionData.ts
index 56b5ec0cb283..23c8c7af3f61 100644
--- a/ui/pages/confirmations/components/confirm/info/hooks/useDecodedTransactionData.ts
+++ b/ui/pages/confirmations/components/confirm/info/hooks/useDecodedTransactionData.ts
@@ -8,6 +8,7 @@ import {
import { decodeTransactionData } from '../../../../../../store/actions';
import { DecodedTransactionDataResponse } from '../../../../../../../shared/types/transaction-decode';
import { currentConfirmationSelector } from '../../../../selectors';
+import { hasTransactionData } from '../../../../../../../shared/modules/transaction.utils';
export function useDecodedTransactionData(): AsyncResult<
DecodedTransactionDataResponse | undefined
@@ -21,7 +22,7 @@ export function useDecodedTransactionData(): AsyncResult<
const transactionData = currentConfirmation?.txParams?.data as Hex;
return useAsyncResult(async () => {
- if (!transactionData?.length) {
+ if (!hasTransactionData(transactionData)) {
return undefined;
}
diff --git a/ui/pages/confirmations/components/confirm/info/hooks/useFourByte.test.ts b/ui/pages/confirmations/components/confirm/info/hooks/useFourByte.test.ts
index 1c3d66570d8b..146cae0771ec 100644
--- a/ui/pages/confirmations/components/confirm/info/hooks/useFourByte.test.ts
+++ b/ui/pages/confirmations/components/confirm/info/hooks/useFourByte.test.ts
@@ -54,7 +54,7 @@ describe('useFourByte', () => {
},
);
- expect(result.current).toBeUndefined();
+ expect(result.current).toBeNull();
});
it("returns undefined if it's not known even if resolution is enabled", () => {
@@ -75,6 +75,6 @@ describe('useFourByte', () => {
},
);
- expect(result.current).toBeUndefined();
+ expect(result.current).toBeNull();
});
});
diff --git a/ui/pages/confirmations/components/confirm/info/hooks/useKnownMethodDataInTransaction.test.ts b/ui/pages/confirmations/components/confirm/info/hooks/useKnownMethodDataInTransaction.test.ts
deleted file mode 100644
index 1c3d66570d8b..000000000000
--- a/ui/pages/confirmations/components/confirm/info/hooks/useKnownMethodDataInTransaction.test.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import { TransactionMeta } from '@metamask/transaction-controller';
-import {
- CONTRACT_INTERACTION_SENDER_ADDRESS,
- genUnapprovedContractInteractionConfirmation,
-} from '../../../../../../../test/data/confirmations/contract-interaction';
-import mockState from '../../../../../../../test/data/mock-state.json';
-import { renderHookWithProvider } from '../../../../../../../test/lib/render-helpers';
-import { useFourByte } from './useFourByte';
-
-describe('useFourByte', () => {
- const depositHexData = '0xd0e30db0';
-
- it('returns the method name and params', () => {
- const currentConfirmation = genUnapprovedContractInteractionConfirmation({
- address: CONTRACT_INTERACTION_SENDER_ADDRESS,
- txData: depositHexData,
- }) as TransactionMeta;
-
- const { result } = renderHookWithProvider(
- () => useFourByte(currentConfirmation),
- {
- ...mockState,
- metamask: {
- ...mockState.metamask,
- use4ByteResolution: true,
- knownMethodData: {
- [depositHexData]: { name: 'Deposit', params: [] },
- },
- },
- },
- );
-
- expect(result.current.name).toEqual('Deposit');
- expect(result.current.params).toEqual([]);
- });
-
- it('returns undefined if resolution is turned off', () => {
- const currentConfirmation = genUnapprovedContractInteractionConfirmation({
- address: CONTRACT_INTERACTION_SENDER_ADDRESS,
- txData: depositHexData,
- }) as TransactionMeta;
-
- const { result } = renderHookWithProvider(
- () => useFourByte(currentConfirmation),
- {
- ...mockState,
- metamask: {
- ...mockState.metamask,
- use4ByteResolution: false,
- knownMethodData: {
- [depositHexData]: { name: 'Deposit', params: [] },
- },
- },
- },
- );
-
- expect(result.current).toBeUndefined();
- });
-
- it("returns undefined if it's not known even if resolution is enabled", () => {
- const currentConfirmation = genUnapprovedContractInteractionConfirmation({
- address: CONTRACT_INTERACTION_SENDER_ADDRESS,
- txData: depositHexData,
- }) as TransactionMeta;
-
- const { result } = renderHookWithProvider(
- () => useFourByte(currentConfirmation),
- {
- ...mockState,
- metamask: {
- ...mockState.metamask,
- use4ByteResolution: true,
- knownMethodData: {},
- },
- },
- );
-
- expect(result.current).toBeUndefined();
- });
-});
diff --git a/ui/pages/confirmations/components/confirm/info/hooks/useKnownMethodDataInTransaction.ts b/ui/pages/confirmations/components/confirm/info/hooks/useKnownMethodDataInTransaction.ts
deleted file mode 100644
index 821fbeaa9b5a..000000000000
--- a/ui/pages/confirmations/components/confirm/info/hooks/useKnownMethodDataInTransaction.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { TransactionMeta } from '@metamask/transaction-controller';
-import { useDispatch, useSelector } from 'react-redux';
-import {
- getKnownMethodData,
- use4ByteResolutionSelector,
-} from '../../../../../../selectors';
-import { getContractMethodData } from '../../../../../../store/actions';
-
-export const useKnownMethodDataInTransaction = (
- currentConfirmation: TransactionMeta,
-) => {
- const dispatch = useDispatch();
- const use4ByteResolution = useSelector(use4ByteResolutionSelector);
- const transactionData = currentConfirmation?.txParams?.data;
- if (use4ByteResolution && transactionData) {
- dispatch(getContractMethodData(currentConfirmation.txParams.data));
- }
- const knownMethodData =
- useSelector((state) => getKnownMethodData(state, transactionData)) || {};
- return { knownMethodData };
-};
diff --git a/ui/pages/confirmations/components/confirm/info/shared/transaction-data/transaction-data.tsx b/ui/pages/confirmations/components/confirm/info/shared/transaction-data/transaction-data.tsx
index cc0eb454ba4b..6ad3899d7aaf 100644
--- a/ui/pages/confirmations/components/confirm/info/shared/transaction-data/transaction-data.tsx
+++ b/ui/pages/confirmations/components/confirm/info/shared/transaction-data/transaction-data.tsx
@@ -28,6 +28,7 @@ import {
DecodedTransactionDataSource,
} from '../../../../../../../../shared/types/transaction-decode';
import { UniswapPathPool } from '../../../../../../../../app/scripts/lib/transaction/decode/uniswap';
+import { hasTransactionData } from '../../../../../../../../shared/modules/transaction.utils';
export const TransactionData = () => {
const currentConfirmation = useSelector(currentConfirmationSelector) as
@@ -43,7 +44,7 @@ export const TransactionData = () => {
return ;
}
- if (!transactionData?.length) {
+ if (!hasTransactionData(transactionData)) {
return null;
}
diff --git a/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.component.js b/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.component.js
index 8caf1043cf4a..5330a3685d47 100644
--- a/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.component.js
+++ b/ui/pages/confirmations/confirm-transaction-base/confirm-transaction-base.component.js
@@ -74,6 +74,7 @@ import FeeDetailsComponent from '../components/fee-details-component/fee-details
import { SimulationDetails } from '../components/simulation-details';
import { fetchSwapsFeatureFlags } from '../../swaps/swaps.util';
import { NetworkChangeToastLegacy } from '../components/confirm/network-change-toast';
+import { hasTransactionData } from '../../../../shared/modules/transaction.utils';
export default class ConfirmTransactionBase extends Component {
static contextTypes = {
@@ -630,7 +631,7 @@ export default class ConfirmTransactionBase extends Component {
const {
txParams: { data },
} = txData;
- if (!data) {
+ if (!hasTransactionData(data)) {
return null;
}
return (
diff --git a/ui/pages/confirmations/token-allowance/token-allowance.js b/ui/pages/confirmations/token-allowance/token-allowance.js
index 123cd1354cc6..8ccd19ecb566 100644
--- a/ui/pages/confirmations/token-allowance/token-allowance.js
+++ b/ui/pages/confirmations/token-allowance/token-allowance.js
@@ -212,7 +212,9 @@ export default function TokenAllowance({
}
const fee = useSelector((state) => transactionFeeSelector(state, fullTxData));
- const methodData = useSelector((state) => getKnownMethodData(state, data));
+ const methodData = useSelector(
+ (state) => getKnownMethodData(state, data) ?? {},
+ );
const { balanceError } = useGasFeeContext();
diff --git a/ui/selectors/selectors.js b/ui/selectors/selectors.js
index 54757979bd44..ad40eeb4e3f2 100644
--- a/ui/selectors/selectors.js
+++ b/ui/selectors/selectors.js
@@ -107,6 +107,7 @@ import { PRIVACY_POLICY_DATE } from '../helpers/constants/privacy-policy';
import { ENVIRONMENT_TYPE_POPUP } from '../../shared/constants/app';
import { MultichainNativeAssets } from '../../shared/constants/multichain/assets';
import { BridgeFeatureFlagsKey } from '../../app/scripts/controllers/bridge/types';
+import { hasTransactionData } from '../../shared/modules/transaction.utils';
import {
getAllUnapprovedTransactions,
getCurrentNetworkTransactions,
@@ -1239,14 +1240,20 @@ export function getRpcPrefsForCurrentProvider(state) {
}
export function getKnownMethodData(state, data) {
- if (!data) {
+ const { knownMethodData, use4ByteResolution } = state.metamask;
+
+ if (!use4ByteResolution || !hasTransactionData(data)) {
return null;
}
+
const prefixedData = addHexPrefix(data);
const fourBytePrefix = prefixedData.slice(0, 10);
- const { knownMethodData, use4ByteResolution } = state.metamask;
- // If 4byte setting is off, we do not want to return the knownMethodData
- return use4ByteResolution ? knownMethodData?.[fourBytePrefix] : undefined;
+
+ if (fourBytePrefix.length < 10) {
+ return null;
+ }
+
+ return knownMethodData?.[fourBytePrefix] ?? null;
}
export function getFeatureFlags(state) {
From d0fb050342bde0d5d10208cf31f7aa1ecc646ebf Mon Sep 17 00:00:00 2001
From: Alex Donesky
Date: Wed, 25 Sep 2024 07:39:55 -0500
Subject: [PATCH 41/43] cherry-pick: remove methods from array used to
determine which requests should be enqueued because they can be safely passed
through (#27315) (#27373)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fix issues that arise when a STX is initated in a dapp and subsequent
method calls were being unnecessarily queued until the STX was complete.
The following methods can be safely removed from the list of methods we
use to determine whether a request should be queued or executed
immediately:
- 'wallet_addEthereumChain'
- 'wallet_requestPermissions',
- 'wallet_requestSnaps',
- 'eth_decrypt',
- 'eth_requestAccounts',
- 'eth_getEncryptionPublicKey',
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27315?quickstart=1)
Fixes: https://github.com/MetaMask/metamask-extension/issues/27098
1. Make sure you have STX enabled from settings
2. Navigate to
https://docs.metamask.io/wallet/reference/eth_sendtransaction/
3. Connect the wallet and switch networks to Sepolia
4. Trigger a TX (call run request)
5. Confirm the transaction and see the STX pending screen
6. Go to test dapp
7. Click Connect --> this needs to happen while STX is pending
8. See that you are able to connect
https://github.com/user-attachments/assets/10be9a20-a22e-4be4-83f6-2bb66ad7a7fa
`wallet_requestPermissions`:
https://github.com/user-attachments/assets/a8ee940c-8d56-4107-8cb1-3683fd244cad
`wallet_requestSnaps`
https://github.com/user-attachments/assets/b4a57a14-8877-4081-82f6-99f2edc9e837
`eth_requestAccounts`
https://github.com/user-attachments/assets/91958cc5-a006-43a4-b4db-37e4b22f07d1
`wallet_addEthereumChain`
https://github.com/user-attachments/assets/23265cf1-3cfb-4e9c-9ea2-599d449d291e
- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
- [ ] 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**
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27373?quickstart=1)
## **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 Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] 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-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
## **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/scripts/metamask-controller.js | 16 ++--------------
shared/constants/methods-tags.ts | 15 ---------------
...pp1-switch-dapp2-eth-request-accounts.spec.js | 14 +++++++++++++-
3 files changed, 15 insertions(+), 30 deletions(-)
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index 3f2a6a32a25a..141fab5aebc8 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -146,10 +146,7 @@ import {
AuthenticationController,
UserStorageController,
} from '@metamask/profile-sync-controller';
-import {
- methodsRequiringNetworkSwitch,
- methodsWithConfirmation,
-} from '../../shared/constants/methods-tags';
+import { methodsRequiringNetworkSwitch } from '../../shared/constants/methods-tags';
///: BEGIN:ONLY_INCLUDE_IF(build-mmi)
import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils';
@@ -5369,16 +5366,7 @@ export default class MetamaskController extends EventEmitter {
this.preferencesController,
),
shouldEnqueueRequest: (request) => {
- if (
- request.method === 'eth_requestAccounts' &&
- this.permissionController.hasPermission(
- request.origin,
- PermissionNames.eth_accounts,
- )
- ) {
- return false;
- }
- return methodsWithConfirmation.includes(request.method);
+ return methodsRequiringNetworkSwitch.includes(request.method);
},
});
engine.push(requestQueueMiddleware);
diff --git a/shared/constants/methods-tags.ts b/shared/constants/methods-tags.ts
index 651109dcedcf..a35954769b1b 100644
--- a/shared/constants/methods-tags.ts
+++ b/shared/constants/methods-tags.ts
@@ -10,24 +10,9 @@ export const methodsRequiringNetworkSwitch = [
'eth_sendTransaction',
'eth_sendRawTransaction',
'wallet_switchEthereumChain',
- 'wallet_addEthereumChain',
'wallet_watchAsset',
'eth_signTypedData',
'eth_signTypedData_v3',
'eth_signTypedData_v4',
'personal_sign',
] as const;
-
-/**
- * This is a list of methods that can cause a confirmation to be
- * presented to the user. Note that some of these methods may
- * only sometimes cause a confirmation to appear.
- */
-export const methodsWithConfirmation = [
- ...methodsRequiringNetworkSwitch,
- 'wallet_requestPermissions',
- 'wallet_requestSnaps',
- 'eth_decrypt',
- 'eth_requestAccounts',
- 'eth_getEncryptionPublicKey',
-];
diff --git a/test/e2e/tests/request-queuing/dapp1-switch-dapp2-eth-request-accounts.spec.js b/test/e2e/tests/request-queuing/dapp1-switch-dapp2-eth-request-accounts.spec.js
index e448c995e077..c1f1ff9de31c 100644
--- a/test/e2e/tests/request-queuing/dapp1-switch-dapp2-eth-request-accounts.spec.js
+++ b/test/e2e/tests/request-queuing/dapp1-switch-dapp2-eth-request-accounts.spec.js
@@ -46,9 +46,21 @@ describe('Request Queuing Dapp 1 Send Tx -> Dapp 2 Request Accounts Tx', functio
// Dapp Send Button
await driver.clickElement('#sendButton');
+ await driver.delay(regularDelayMs);
+ await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);
- // Leave the confirmation pending
+ await driver.waitForSelector({
+ text: 'Reject',
+ tag: 'button',
+ });
+ await driver.delay(regularDelayMs);
+
+ await driver.switchToWindowWithTitle(
+ WINDOW_TITLES.ExtensionInFullScreenView,
+ );
+
+ // Leave the confirmation pending
await openDapp(driver, undefined, DAPP_ONE_URL);
const accountsOnload = await (
From eca8bdbf6bf825c21cb42251c848d93774de7c3b Mon Sep 17 00:00:00 2001
From: Dan J Miller
Date: Wed, 25 Sep 2024 11:20:51 -0230
Subject: [PATCH 42/43] Fix changelog lint error
---
CHANGELOG.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a85cc7765266..8dc197f1b88f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -363,6 +363,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- chore(deps): bump assets controller to v34.0.0 ([#25540](https://github.com/MetaMask/metamask-extension/pull/25540))
- chore: add bridge controller, store and api utils ([#25044](https://github.com/MetaMask/metamask-extension/pull/25044))
- fix: add eth_signTypedData and eth_signTypedData_v3 to `methodsRequiringNetworkSwitch` ([#25562](https://github.com/MetaMask/metamask-extension/pull/25562))
+
## [12.2.4]
### Fixed
- Fixes token approvals for users who have the "Decode smart contracts" setting toggled off ([#27203](https://github.com/MetaMask/metamask-extension/pull/27203))
@@ -5410,8 +5411,7 @@ Update styles and spacing on the critical error page ([#20350](https://github.c
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v12.3.0...HEAD
-[12.3.0]: https://github.com/MetaMask/metamask-extension/compare/v12.2.2...v12.3.0
-[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v12.2.4...HEAD
+[12.3.0]: https://github.com/MetaMask/metamask-extension/compare/v12.2.4...v12.3.0
[12.2.4]: https://github.com/MetaMask/metamask-extension/compare/v12.2.3...v12.2.4
[12.2.3]: https://github.com/MetaMask/metamask-extension/compare/v12.2.2...v12.2.3
[12.2.2]: https://github.com/MetaMask/metamask-extension/compare/v12.2.1...v12.2.2
From 318aaadfab1abfe56abd59beb3da6ae9308f9ea3 Mon Sep 17 00:00:00 2001
From: Marina Boboc <120041701+benjisclowder@users.noreply.github.com>
Date: Wed, 25 Sep 2024 18:47:22 +0300
Subject: [PATCH 43/43] Update v12.3.0 Changelog (#27274)
## **Description**
Adding changelog for v12.3.0 RC.
[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27274?quickstart=1)
---------
Co-authored-by: Dan J Miller
---
CHANGELOG.md | 410 +++++++--------------------------------------------
1 file changed, 53 insertions(+), 357 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8dc197f1b88f..199b83700dde 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,362 +7,59 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [12.3.0]
-### Fixed
-- Merge branch 'Version-v12.2.0' into Version-v12.3.0
-- Merge remote-tracking branch 'origin/master' into Version-v12.2.0
-- CherryPick: "fix: issue where `wallet_addEtherumChain` was incorrectly enforcing inclusion of a blockExplorerUrls property which is not required (#26938)" ([#26938](https://github.com/MetaMask/metamask-extension/pull/26938))
-- fix: update notifications events (#26807) ([#26807](https://github.com/MetaMask/metamask-extension/pull/26807))
-- Update v12.2.0 with changes from v12.1.2 ([#26895](https://github.com/MetaMask/metamask-extension/pull/26895))
-- Merge remote-tracking branch 'origin/master' into sync-v12.1.2
-- perf(cherry-pick): use an interstitial page to load `popup.html`; load scripts using `defer`ed script tags (#26555) ([#26555](https://github.com/MetaMask/metamask-extension/pull/26555))
-- v12.2.0 sync v12.1.1 ([#26842](https://github.com/MetaMask/metamask-extension/pull/26842))
-- Merge branch 'Version-v12.2.0' into v12.2.0-sync-v12.1.1
-- ci: Prevent E2E timeouts on release changes (#26846) [cherry-pick] ([#26846](https://github.com/MetaMask/metamask-extension/pull/26846))
-- Fix type error
-- Fix changelog merge conflicts
-- Update LavaMoat policies
-- Run yarn dedupe
-- Update LavaMoat policies
-- Merge branch 'Version-v12.2.0' into v12.2.0-sync-v12.1.1
-- chore: MMI adds cherry pick for PR 25967 ([#26736](https://github.com/MetaMask/metamask-extension/pull/26736))
-- Merge remote-tracking branch 'origin/Version-v12.2.0' into v12.2.0-sync-v12.1.1
-- Merge remote-tracking branch 'origin/master' into v12.2.0-sync-v12.1.1
-- fix(cherry-pick): remove BTC accounts from send flow (#26271) ([#26271](https://github.com/MetaMask/metamask-extension/pull/26271))
-- feat(cherry-pick): support creation of Bitcoin testnet accounts (#25772) ([#25772](https://github.com/MetaMask/metamask-extension/pull/25772))
-- fix(cherry-pick): remove btc account from permission connect lists (#25980) ([#25980](https://github.com/MetaMask/metamask-extension/pull/25980))
-- fix(cherry-pick): remove submitRequest from dapp permission (#26319) ([#26319](https://github.com/MetaMask/metamask-extension/pull/26319))
-- chore: update @metamask/bitcoin-wallet-snap to 0.5.0 ([#26701](https://github.com/MetaMask/metamask-extension/pull/26701))
-- chore: update @metamask/bitcoin-wallet-snap to 0.4.0 ([#26229](https://github.com/MetaMask/metamask-extension/pull/26229))
-- chore: update @metamask/bitcoin-wallet-snap to 0.3.0 ([#26168](https://github.com/MetaMask/metamask-extension/pull/26168))
-- chore: update Bitcoin Snap to version 0.2.5 ([#26058](https://github.com/MetaMask/metamask-extension/pull/26058))
-- fix(multichain): use accounts{Added,Removed} to fetch/clear balances ([#25884](https://github.com/MetaMask/metamask-extension/pull/25884))
-- feat: add BTC support survey link ([#25875](https://github.com/MetaMask/metamask-extension/pull/25875))
-- Cherrypick flaky test fix 12.2.0 ([#26747](https://github.com/MetaMask/metamask-extension/pull/26747))
-- chore: cherry pick remove token and nft detection modals (#26403) ([#26403](https://github.com/MetaMask/metamask-extension/pull/26403))
-- Synchronize v12.2.0 RC with v12.1.0 ([#26729](https://github.com/MetaMask/metamask-extension/pull/26729))
-- Merge remote-tracking branch 'origin/master' into v12.2.0-sync-master
-- v12.2.0 sync with v12.1.0 ([#26695](https://github.com/MetaMask/metamask-extension/pull/26695))
-- Fix Sentry state merge conflict error
-- fix cherry-pick test: UX: Multichain: Add E2E for signaling network change from Netwo… ([#26704](https://github.com/MetaMask/metamask-extension/pull/26704))
-- test: Removed step from e2e tests ([#25910](https://github.com/MetaMask/metamask-extension/pull/25910))
-- Update LavaMoat policies
-- Resolve changelog conflicts
-- DResolve audit advisory
-- Merge remote-tracking branch 'origin/Version-v12.1.0' into v12.2.0-sync-with-v12.1.0
-- Patch fix for initial connections in preinstalled Snaps ([#26602](https://github.com/MetaMask/metamask-extension/pull/26602))
-- add version in changelog/package.json files ([#25766](https://github.com/MetaMask/metamask-extension/pull/25766))
-- chore: Master sync ([#26395](https://github.com/MetaMask/metamask-extension/pull/26395))
-- chore: Bump Snaps packages ([#26086](https://github.com/MetaMask/metamask-extension/pull/26086))
-- fix: Improve AccountListMenu/Item performance ([#26379](https://github.com/MetaMask/metamask-extension/pull/26379))
-- fix: Codespaces `corepack enable` ([#25161](https://github.com/MetaMask/metamask-extension/pull/25161))
-- fix: display toast message if user quickly sends transaction on different networks ([#26114](https://github.com/MetaMask/metamask-extension/pull/26114))
-- fix: problem with origins in the Snaps permission UI ([#26422](https://github.com/MetaMask/metamask-extension/pull/26422))
-- feat: Add abstraction for Snaps permissions ([#25175](https://github.com/MetaMask/metamask-extension/pull/25175))
-- test: add transaction contract interaction integration tests ([#26272](https://github.com/MetaMask/metamask-extension/pull/26272))
-- fix: timeout and "Rerun failed tests" ([#26239](https://github.com/MetaMask/metamask-extension/pull/26239))
-- chore: migrate BridgeController to BaseController v2 ([#26109](https://github.com/MetaMask/metamask-extension/pull/26109))
-- feat: Enable why did you render ([#26339](https://github.com/MetaMask/metamask-extension/pull/26339))
-- fix: Delete invalid `SelectedNetworkController` state ([#26428](https://github.com/MetaMask/metamask-extension/pull/26428))
-- test: ensure bridge button handles clicks according to feature flags ([#25812](https://github.com/MetaMask/metamask-extension/pull/25812))
-- build(webpack): polyfill `setImmediate` ([#26398](https://github.com/MetaMask/metamask-extension/pull/26398))
-- feat: feature-flagged cross-chain swaps route [METABRIDGE-867] ([#25811](https://github.com/MetaMask/metamask-extension/pull/25811))
-- chore: Remove i18n translations from Developer Options Settings Page ([#26380](https://github.com/MetaMask/metamask-extension/pull/26380))
-- fix: Do not break application if no token details are found using getTokenStandardAndDetails ([#26324](https://github.com/MetaMask/metamask-extension/pull/26324))
-- fix: Flaky contract interaction test ([#26420](https://github.com/MetaMask/metamask-extension/pull/26420))
-- fix: Enter key on Create Account checkbox should not trigger show/hide ([#26394](https://github.com/MetaMask/metamask-extension/pull/26394))
-- fix: notifications use better events ([#26410](https://github.com/MetaMask/metamask-extension/pull/26410))
-- fix: Restore snaps-controllers version following patch ([#26412](https://github.com/MetaMask/metamask-extension/pull/26412))
-- fix: Improve hex copy button ([#26384](https://github.com/MetaMask/metamask-extension/pull/26384))
-- refactor: use core profile syncing controllers. ([#26370](https://github.com/MetaMask/metamask-extension/pull/26370))
-- test: snap account contract interaction ([#26234](https://github.com/MetaMask/metamask-extension/pull/26234))
-- feat: updated SSK version in e2e and added test for creating multiple… ([#26378](https://github.com/MetaMask/metamask-extension/pull/26378))
-- Merge origin/develop into master-sync
-- chore: MMI move duck and selector to TS ([#26125](https://github.com/MetaMask/metamask-extension/pull/26125))
-- refactor(notifications): use contentful package as dev dependency ([#26381](https://github.com/MetaMask/metamask-extension/pull/26381))
-- fix: remove submitRequest from dapp permission ([#26319](https://github.com/MetaMask/metamask-extension/pull/26319))
-- feat: Add integration test for blockaid on contract interaction ([#26366](https://github.com/MetaMask/metamask-extension/pull/26366))
-- refactor: add performance tracing infrastructure ([#26044](https://github.com/MetaMask/metamask-extension/pull/26044))
-- refactor: replace deprecated mixins with Text component in slippage-buttons ([#25638](https://github.com/MetaMask/metamask-extension/pull/25638))
-- refactor: replace deprecated mixins with text component in loading-swaps-quotes ([#25553](https://github.com/MetaMask/metamask-extension/pull/25553))
-- feat: Add metrics for alerts (transactions redesign) ([#26121](https://github.com/MetaMask/metamask-extension/pull/26121))
-- fix(25350): fix flakey token importing e2e test ([#26351](https://github.com/MetaMask/metamask-extension/pull/26351))
-- fix: enable Save button on Add Contact page for address input ([#26155](https://github.com/MetaMask/metamask-extension/pull/26155))
-- test: Add test for migration 120.2 and fix docs ([#26333](https://github.com/MetaMask/metamask-extension/pull/26333))
-- chore: normalize separator in `content` on the `viewport` `meta` tag ([#26268](https://github.com/MetaMask/metamask-extension/pull/26268))
-- fix: Stop logging pipeline stream errors in the service worker if they match 'Premature close' ([#26336](https://github.com/MetaMask/metamask-extension/pull/26336))
-- build: add alternative build process to enable faster developer builds ([#22506](https://github.com/MetaMask/metamask-extension/pull/22506))
-- fix: issue where `setNetworkClientIdForDomain` was called without checking whether the origin was eligible for setting its own network ([#26323](https://github.com/MetaMask/metamask-extension/pull/26323))
-- fix: get permit and order signatures token decimals ([#26292](https://github.com/MetaMask/metamask-extension/pull/26292))
-- feat: Update Redesign Signature Permit to show ellipsis at max 15 digits ([#26227](https://github.com/MetaMask/metamask-extension/pull/26227))
-- fix: remove the ability to send to btc accounts in send page ([#26271](https://github.com/MetaMask/metamask-extension/pull/26271))
-- fix: Adding migration 125 to remove Deprecated TxController Key from state ([#26267](https://github.com/MetaMask/metamask-extension/pull/26267))
-- fix: Revert "fix: remove submitRequest from dapp permission" ([#26293](https://github.com/MetaMask/metamask-extension/pull/26293))
-- refactor: convert `icon-factory.js` to typescript ([#23823](https://github.com/MetaMask/metamask-extension/pull/23823))
-- fix(26065): remove persisted state mostRecentRetrievedState after initialization if no errors ([#26206](https://github.com/MetaMask/metamask-extension/pull/26206))
-- refactor: ENABLE_MV3 flag cleanup ([#26059](https://github.com/MetaMask/metamask-extension/pull/26059))
-- test: fix flaky test Import flow @no-mmi Import wallet using Secret Recovery Phrase ([#26275](https://github.com/MetaMask/metamask-extension/pull/26275))
-- chore: Fully remove `eth_sign` ([#24756](https://github.com/MetaMask/metamask-extension/pull/24756))
-- fix: remove submitRequest from dapp permission ([#26276](https://github.com/MetaMask/metamask-extension/pull/26276))
-- chore: Update `actions/cache` from v3 to v4 ([#26020](https://github.com/MetaMask/metamask-extension/pull/26020))
-- feat: QR-based add NGRAVE ZERO Hardware ([#25080](https://github.com/MetaMask/metamask-extension/pull/25080))
-- fix: Fix GitHub release description ([#26247](https://github.com/MetaMask/metamask-extension/pull/26247))
-- feat(btc): use new snap account flow for Bitcoin accounts ([#26183](https://github.com/MetaMask/metamask-extension/pull/26183))
-- refactor: replace deprecated mixins with text component in transaction-confirmed ([#25551](https://github.com/MetaMask/metamask-extension/pull/25551))
-- fix: improve warning in add network modal ([#26250](https://github.com/MetaMask/metamask-extension/pull/26250))
-- fix: Fix `create_release_pull_request` OOM error ([#26249](https://github.com/MetaMask/metamask-extension/pull/26249))
-- chore: Create a story for TokenCurrencyDisplay component ([#26172](https://github.com/MetaMask/metamask-extension/pull/26172))
-- chore: refactoring onboarding to remove deprecated components ([#26207](https://github.com/MetaMask/metamask-extension/pull/26207))
-- fix: Fix CircleCI `create_release_pull_request` job ([#26246](https://github.com/MetaMask/metamask-extension/pull/26246))
-- fix: flaky test `Import flow @no-mmi Import Account using json file` ([#26240](https://github.com/MetaMask/metamask-extension/pull/26240))
-- fix: sentry sessions ([#26192](https://github.com/MetaMask/metamask-extension/pull/26192))
-- test: [Page Object Model] rename process to flow ([#26228](https://github.com/MetaMask/metamask-extension/pull/26228))
-- test: header integration test for contract interaction ([#25981](https://github.com/MetaMask/metamask-extension/pull/25981))
-- chore: Pass along hashed `rpcUrl` during `CustomNetworkAdded` event ([#26203](https://github.com/MetaMask/metamask-extension/pull/26203))
-- chore: Create a story for PageContainerHeader component ([#26031](https://github.com/MetaMask/metamask-extension/pull/26031))
-- chore: Create a story for GasTiming component ([#25557](https://github.com/MetaMask/metamask-extension/pull/25557))
-- New Crowdin translations by Github Action ([#26230](https://github.com/MetaMask/metamask-extension/pull/26230))
-- chore: update @metamask/bitcoin-wallet-snap to 0.4.0 ([#26229](https://github.com/MetaMask/metamask-extension/pull/26229))
-- fix: flaky test `Sentry errors before initialization, after opting into metrics @no-mmi should send error events in background` ([#26216](https://github.com/MetaMask/metamask-extension/pull/26216))
-- chore: Create a story for NftCollectionImage component ([#26069](https://github.com/MetaMask/metamask-extension/pull/26069))
-- fix: update icons ([#26180](https://github.com/MetaMask/metamask-extension/pull/26180))
-- refactor: replace Typography with Text component in restore-vault.js ([#25636](https://github.com/MetaMask/metamask-extension/pull/25636))
-- chore: Create a story for convert-token-to-nft-modal component ([#25561](https://github.com/MetaMask/metamask-extension/pull/25561))
-- refactor: replace deprecated mixins with Text component in qr-code-view ([#25637](https://github.com/MetaMask/metamask-extension/pull/25637))
-- test: Add manual scenario for network polling scenario ([#26195](https://github.com/MetaMask/metamask-extension/pull/26195))
-- feat: Add experimental settings toggle for transactions redesign ([#26010](https://github.com/MetaMask/metamask-extension/pull/26010))
-- feat: Support Permit variants: PermitSingle, PermitBatch, PermitTransferFrom, PermitBatchTransferFrom, TradeOrder, Seaport ([#26107](https://github.com/MetaMask/metamask-extension/pull/26107))
-- feat: updated dapp permission screen ([#25703](https://github.com/MetaMask/metamask-extension/pull/25703))
-- fix: improve performance in large signature request confirmations ([#26209](https://github.com/MetaMask/metamask-extension/pull/26209))
-- refactor: remove password manager mention ([#25985](https://github.com/MetaMask/metamask-extension/pull/25985))
-- New Crowdin translations by Github Action ([#25939](https://github.com/MetaMask/metamask-extension/pull/25939))
-- chore: remove opera manifest files as they are not used ([#26200](https://github.com/MetaMask/metamask-extension/pull/26200))
-- fix(deps): bump fast-xml-parser from 4.3.4 to 4.4.1. ([#26202](https://github.com/MetaMask/metamask-extension/pull/26202))
-- test: [Snaps E2E] remove unnecessary steps from snaps UI Images test ([#25640](https://github.com/MetaMask/metamask-extension/pull/25640))
-- fix: truncate long tokenId ([#26179](https://github.com/MetaMask/metamask-extension/pull/26179))
-- chore: Add en_GB locale ([#26196](https://github.com/MetaMask/metamask-extension/pull/26196))
-- chore: upgrade to Sentry 8 ([#25999](https://github.com/MetaMask/metamask-extension/pull/25999))
-- refactor: add unlock checks for notification related controllers ([#26189](https://github.com/MetaMask/metamask-extension/pull/26189))
-- fix: interpret multipart errors correctly and allow ignore ([#26113](https://github.com/MetaMask/metamask-extension/pull/26113))
-- feat: migrate global unit tests from Mocha to Jest ([#26104](https://github.com/MetaMask/metamask-extension/pull/26104))
-- fix: node being setup twice ([#26052](https://github.com/MetaMask/metamask-extension/pull/26052))
-- fix: setupControllerConnection outstream end event listener ([#26141](https://github.com/MetaMask/metamask-extension/pull/26141))
-- fix: Address performance issues with 'Portfolio Dashboard' loading in test environment ([#26182](https://github.com/MetaMask/metamask-extension/pull/26182))
-- chore: migrating interactive-replacement-token-page to ts ([#26115](https://github.com/MetaMask/metamask-extension/pull/26115))
-- feat: (cherry-pick)(Version v12.2.0) Migration #122 set redesignedConfirmationsEnabled to true ([#26139](https://github.com/MetaMask/metamask-extension/pull/26139))
-- chore: update @metamask/bitcoin-wallet-snap to 0.3.0 ([#26168](https://github.com/MetaMask/metamask-extension/pull/26168))
-- test: fix potential api-spec test race condition when adding to task queue ([#26171](https://github.com/MetaMask/metamask-extension/pull/26171))
-- fix(user-preference-currency-display): remove unused prop ethLogoHeight ([#24517](https://github.com/MetaMask/metamask-extension/pull/24517))
-- fix: update logos for flare-mainnet and songbird ([#25560](https://github.com/MetaMask/metamask-extension/pull/25560))
-- feat: define account name during creation ([#25191](https://github.com/MetaMask/metamask-extension/pull/25191))
-- chore: MMI move custody component to TS ([#26096](https://github.com/MetaMask/metamask-extension/pull/26096))
-- chore: add portfolio ephemeral domain URL ([#26163](https://github.com/MetaMask/metamask-extension/pull/26163))
-- fix: Flaky test `4byte setting ` ([#26111](https://github.com/MetaMask/metamask-extension/pull/26111))
-- fix: PPOM blockaid update ([#26154](https://github.com/MetaMask/metamask-extension/pull/26154))
-- fix: flaky BTC e2e tests ([#26082](https://github.com/MetaMask/metamask-extension/pull/26082))
-- chore: Add extra event props ([#26123](https://github.com/MetaMask/metamask-extension/pull/26123))
-- refactor: fix event names used to track notifications ([#25521](https://github.com/MetaMask/metamask-extension/pull/25521))
-- test: [Snaps E2E] Create test for snap dialog JSX functionality ([#25493](https://github.com/MetaMask/metamask-extension/pull/25493))
-- chore: update BNB logos ([#26140](https://github.com/MetaMask/metamask-extension/pull/26140))
-- fix: enable siwe redesign ([#26136](https://github.com/MetaMask/metamask-extension/pull/26136))
-- chore: cleanup `.prettierignore` file ([#24828](https://github.com/MetaMask/metamask-extension/pull/24828))
-- chore: Bump `@metamask/ens-controller` to v12 ([#26127](https://github.com/MetaMask/metamask-extension/pull/26127))
-- chore: Bump `@metamask/transaction-controller` to v34 ([#26124](https://github.com/MetaMask/metamask-extension/pull/26124))
-- Revert "test: Adding e2e for SIWE and re-enabling redesign for SIWE (#25831)" ([#25831](https://github.com/MetaMask/metamask-extension/pull/25831))
-- chore: Create a story for Snackbar component ([#25515](https://github.com/MetaMask/metamask-extension/pull/25515))
-- fix: add new helper function for `openMenuSafe` to mitigate all ocurrences for opening menu with MMI build ([#26079](https://github.com/MetaMask/metamask-extension/pull/26079))
-- test: Adding e2e for SIWE and re-enabling redesign for SIWE (#25831) ([#25831](https://github.com/MetaMask/metamask-extension/pull/25831))
-- feat: make add-team-label use the reusable workflow ([#25807](https://github.com/MetaMask/metamask-extension/pull/25807))
-- chore: MMI-5301 adds enums for custody type and status ([#26006](https://github.com/MetaMask/metamask-extension/pull/26006))
-- feat: Move ENABLE_CONFIRMATION_REDESIGN feature flag to the developer… ([#26095](https://github.com/MetaMask/metamask-extension/pull/26095))
-- fix: remove btc account from permission connect lists ([#25980](https://github.com/MetaMask/metamask-extension/pull/25980))
-- feat: update network list item to include start accessory and end ([#25507](https://github.com/MetaMask/metamask-extension/pull/25507))
-- chore: mmi 5305 mmi pages typescript migration ([#26081](https://github.com/MetaMask/metamask-extension/pull/26081))
-- fix: Move Snaps hooks out of code fence ([#26120](https://github.com/MetaMask/metamask-extension/pull/26120))
-- feat: Mitigate risk for distracted users on queued transactions from different dApps ([#25852](https://github.com/MetaMask/metamask-extension/pull/25852))
-- fix: lock Chrome version to 126 (#26101) ([#26101](https://github.com/MetaMask/metamask-extension/pull/26101))
-- feat: Add metrics event for advanced details section toggling ([#26083](https://github.com/MetaMask/metamask-extension/pull/26083))
-- fix: display link to privacy-policy explanation in onboarding flow ([#26038](https://github.com/MetaMask/metamask-extension/pull/26038))
-- chore: Create a story for InvalidCustomNetworkAlert component ([#25600](https://github.com/MetaMask/metamask-extension/pull/25600))
-- fix: number formatting on swap + send tx detail ([#26029](https://github.com/MetaMask/metamask-extension/pull/26029))
-- fix: Flaky test `Account Custom Name..` ([#26062](https://github.com/MetaMask/metamask-extension/pull/26062))
-- fix: snap flakiness on `installSnapSimpleKeyring` function ([#26039](https://github.com/MetaMask/metamask-extension/pull/26039))
-- fix: lock Chrome version to 126 ([#26101](https://github.com/MetaMask/metamask-extension/pull/26101))
-- fix: remove halo for tokens ([#26016](https://github.com/MetaMask/metamask-extension/pull/26016))
-- refactor: replace typography with text component in creation-successful.js ([#25552](https://github.com/MetaMask/metamask-extension/pull/25552))
-- fix: `vault decryption` broken tests due to update on window handling ([#26074](https://github.com/MetaMask/metamask-extension/pull/26074))
-- docs: Centralize Author/Team Mapping for Commit Tracking ([#25986](https://github.com/MetaMask/metamask-extension/pull/25986))
-- fix: flaky test: Check the toggle for hex data ([#25899](https://github.com/MetaMask/metamask-extension/pull/25899))
-- chore: migrated institutional ui components to ts ([#25858](https://github.com/MetaMask/metamask-extension/pull/25858))
-- chore: removed unused component ([#26000](https://github.com/MetaMask/metamask-extension/pull/26000))
-- chore: update Bitcoin Snap to version 0.2.5 ([#26058](https://github.com/MetaMask/metamask-extension/pull/26058))
-- refactor: replace Typography with Text component in metametrics.js ([#25630](https://github.com/MetaMask/metamask-extension/pull/25630))
-- refactor: replace typography with text component in review recovery phrase ([#25265](https://github.com/MetaMask/metamask-extension/pull/25265))
-- test: new switchToWindowWithTitle w/ Extension communication ([#25362](https://github.com/MetaMask/metamask-extension/pull/25362))
-- ci: Trimming the gitdiff output before writing to output file ([#26057](https://github.com/MetaMask/metamask-extension/pull/26057))
-- chore: tweak send page styling ([#25982](https://github.com/MetaMask/metamask-extension/pull/25982))
-- fix: mmi flaky tests `Reveal SRP through settings completes quiz and reveals SRP QR after wrong answers` , `Sign Typed Data Signature Request can initiate and reject a Signature Request of Sign Typed Data`, `Sign Typed Data Signature Request can queue multiple Signature Requests of Sign Typed Data and confirm` ([#26055](https://github.com/MetaMask/metamask-extension/pull/26055))
-- chore: Create a story for IconButton component ([#25277](https://github.com/MetaMask/metamask-extension/pull/25277))
-- fix: center token icon ([#26013](https://github.com/MetaMask/metamask-extension/pull/26013))
-- fix: flaky test `Import flow @no-mmi Import wallet using Secret Recovery Phrase with pasting word by word` ([#26049](https://github.com/MetaMask/metamask-extension/pull/26049))
-- fix: flaky test 25912 ([#25913](https://github.com/MetaMask/metamask-extension/pull/25913))
-- chore: add privacy query params to portfolio navigation ([#25958](https://github.com/MetaMask/metamask-extension/pull/25958))
-- fix: (cherry-pick) Remove special reject button case from api spec tests (#26048) ([#26048](https://github.com/MetaMask/metamask-extension/pull/26048))
-- chore: Temporarily disable Playwright Swaps tests ([#26050](https://github.com/MetaMask/metamask-extension/pull/26050))
-- fix: Remove special reject button case from api spec tests ([#26048](https://github.com/MetaMask/metamask-extension/pull/26048))
-- test(e2e): unlock trezor account ([#25824](https://github.com/MetaMask/metamask-extension/pull/25824))
-- fix: Flaky "Signature Approved Event" e2e test ([#26040](https://github.com/MetaMask/metamask-extension/pull/26040))
-- feat: Migration #122 set redesignedConfirmationsEnabled to true ([#25769](https://github.com/MetaMask/metamask-extension/pull/25769))
-- fix: Revert "refactor: use withKeyring method (#25435)" ([#25435](https://github.com/MetaMask/metamask-extension/pull/25435))
-- fix: :label: update the text in the popup to enable notifications ([#26026](https://github.com/MetaMask/metamask-extension/pull/26026))
-- fix: map the supported block explorers ([#25908](https://github.com/MetaMask/metamask-extension/pull/25908))
-- fix: update css for modals ([#25961](https://github.com/MetaMask/metamask-extension/pull/25961))
-- fix: Fix permssions for `update-attributions` workflow ([#26019](https://github.com/MetaMask/metamask-extension/pull/26019))
-- fix: add migration for profile syncing controller ([#26004](https://github.com/MetaMask/metamask-extension/pull/26004))
-- test: Adding e2e for SIWE and re-enabling redesign for SIWE ([#25831](https://github.com/MetaMask/metamask-extension/pull/25831))
-- test: UX: Multichain: Add E2E for signaling network change from Network menu to dapp, Autoswitching networks ([#25765](https://github.com/MetaMask/metamask-extension/pull/25765))
-- feat: Move ENABLE_CONFIRMATION_REDESIGN feature flag to the developer settings page ([#25520](https://github.com/MetaMask/metamask-extension/pull/25520))
-- fix: `yarn:start:test:flask` is broken `Lavapack is not defined` ([#25995](https://github.com/MetaMask/metamask-extension/pull/25995))
-- feat: add utility function to get supported chains from the Security Alerts API ([#25716](https://github.com/MetaMask/metamask-extension/pull/25716))
-- fix: `vault-decryption` test since the order of announcement modals changed ([#25997](https://github.com/MetaMask/metamask-extension/pull/25997))
-- fix: updated switch to this account condition ([#25609](https://github.com/MetaMask/metamask-extension/pull/25609))
-- fix: flaky test Settings Redirects to ENS domains when user inputs ENS into address bar ([#25782](https://github.com/MetaMask/metamask-extension/pull/25782))
-- chore: MMI-5248 introduce the token allowance functionality for MMI ([#25967](https://github.com/MetaMask/metamask-extension/pull/25967))
-- fix: vertically align asset image ([#25988](https://github.com/MetaMask/metamask-extension/pull/25988))
-- feat: Adding state per window in e2e, excluding null state ([#25900](https://github.com/MetaMask/metamask-extension/pull/25900))
-- fix: attribution link ([#25947](https://github.com/MetaMask/metamask-extension/pull/25947))
-- feat: Enable hardware wallets for smart transactions in swaps ([#25742](https://github.com/MetaMask/metamask-extension/pull/25742))
-- fix: fix link redirection ([#25983](https://github.com/MetaMask/metamask-extension/pull/25983))
-- fix: fix overlapping modals ([#25962](https://github.com/MetaMask/metamask-extension/pull/25962))
-- feat: Show the Close extension button on the Smart Transaction Status Page for a pending dapp transaction ([#25965](https://github.com/MetaMask/metamask-extension/pull/25965))
-- fix(multichain): use accounts{Added,Removed} to fetch/clear balances ([#25884](https://github.com/MetaMask/metamask-extension/pull/25884))
-- test: Add integration tests for permit simulation section ([#25856](https://github.com/MetaMask/metamask-extension/pull/25856))
-- fix: fixed max width for permissions page ([#25870](https://github.com/MetaMask/metamask-extension/pull/25870))
-- fix: show current network if domains are undefined ([#25960](https://github.com/MetaMask/metamask-extension/pull/25960))
-- fix: notification slowness and crashes ([#25946](https://github.com/MetaMask/metamask-extension/pull/25946))
-- ci: Disabling non-lint CI on the l10n_crowdin_action branch ([#25809](https://github.com/MetaMask/metamask-extension/pull/25809))
-- refactor: use `withKeyring` method ([#25435](https://github.com/MetaMask/metamask-extension/pull/25435))
-- feat: add BTC support survey link ([#25875](https://github.com/MetaMask/metamask-extension/pull/25875))
-- fix: re-organize files under assets folder ([#25897](https://github.com/MetaMask/metamask-extension/pull/25897))
-- fix: fix css nft detail ([#25931](https://github.com/MetaMask/metamask-extension/pull/25931))
-- fix: Implement Auto-Enable Feature for Basic Functionality in Metamask Extension v12.1.0 ([#25944](https://github.com/MetaMask/metamask-extension/pull/25944))
-- fix: Handle error when offscreen document already exists ([#25138](https://github.com/MetaMask/metamask-extension/pull/25138))
-- test: Expand coverage of sourcemap validator ([#25115](https://github.com/MetaMask/metamask-extension/pull/25115))
-- feat: Add full screen Snap Home and Dialog ([#25670](https://github.com/MetaMask/metamask-extension/pull/25670))
-- chore: swaps codeowners reorg ([#24803](https://github.com/MetaMask/metamask-extension/pull/24803))
-- fix: track token detection enabled ([#25822](https://github.com/MetaMask/metamask-extension/pull/25822))
-- fix: rm locales in other languages ([#25936](https://github.com/MetaMask/metamask-extension/pull/25936))
-- fix: fix ([#25907](https://github.com/MetaMask/metamask-extension/pull/25907))
-- fix: password reset ([#25847](https://github.com/MetaMask/metamask-extension/pull/25847))
-- New Crowdin translations by Github Action ([#24889](https://github.com/MetaMask/metamask-extension/pull/24889))
-- fix: Remove abandoned test:unit:jest command ([#25905](https://github.com/MetaMask/metamask-extension/pull/25905))
-- fix(22851): check if active device to prevent autoconnect for hw ([#25503](https://github.com/MetaMask/metamask-extension/pull/25503))
-- test: Removed step from e2e tests ([#25910](https://github.com/MetaMask/metamask-extension/pull/25910))
-- fix: calcTokenAmount BigNumber more than 15 digits error ([#25799](https://github.com/MetaMask/metamask-extension/pull/25799))
-- feat: add custom form check alerts ([#25259](https://github.com/MetaMask/metamask-extension/pull/25259))
-- fix: test failure on firefox ([#25895](https://github.com/MetaMask/metamask-extension/pull/25895))
-- fix: disables "swap and send" for MMI ([#25886](https://github.com/MetaMask/metamask-extension/pull/25886))
-- fix: Fixed flaky test 24645 ([#25786](https://github.com/MetaMask/metamask-extension/pull/25786))
-- chore: refactor SwapsController so it extends from BaseControllerV2 ([#25681](https://github.com/MetaMask/metamask-extension/pull/25681))
-- feat: Replace "Manage in settings" with "No thanks" in the STX Opt In modal, only show the modal for non-zero balances ([#25848](https://github.com/MetaMask/metamask-extension/pull/25848))
-- feat: Display advanced section within confirmation by default for some users ([#25687](https://github.com/MetaMask/metamask-extension/pull/25687))
-- chore: bump assets-controllers to v36.0.0 ([#25857](https://github.com/MetaMask/metamask-extension/pull/25857))
-- fix: add name to scuttling exception list ([#25849](https://github.com/MetaMask/metamask-extension/pull/25849))
-- fix: update build version to align with firefox's newer version restrictions ([#25456](https://github.com/MetaMask/metamask-extension/pull/25456))
-- feat: regression label ([#25691](https://github.com/MetaMask/metamask-extension/pull/25691))
-- chore: Master sync ([#25816](https://github.com/MetaMask/metamask-extension/pull/25816))
-- fix: contract data in metrics ([#25759](https://github.com/MetaMask/metamask-extension/pull/25759))
-- fix: flaky test `ERC721 NFTs testdapp interaction` ([#25854](https://github.com/MetaMask/metamask-extension/pull/25854))
-- fix: flaky test `Create BTC Account cannot create multiple BTC accounts...` ([#25861](https://github.com/MetaMask/metamask-extension/pull/25861))
-- feat: support creation of Bitcoin testnet accounts ([#25772](https://github.com/MetaMask/metamask-extension/pull/25772))
-- fix: use of an header in a dedicated call ([#25828](https://github.com/MetaMask/metamask-extension/pull/25828))
-- feat(tests): add btc e2e tests ([#25663](https://github.com/MetaMask/metamask-extension/pull/25663))
-- feat: NFT details new design ([#25524](https://github.com/MetaMask/metamask-extension/pull/25524))
-- feat: Add fuzzy matching for name lookup ([#25264](https://github.com/MetaMask/metamask-extension/pull/25264))
-- fix: edit path to dist folder ([#25826](https://github.com/MetaMask/metamask-extension/pull/25826))
-- chore: update @metamask/bitcoin-wallet-snap to 0.2.4 (#25808) ([#25808](https://github.com/MetaMask/metamask-extension/pull/25808))
-- chore: Patch security issue in snaps-utils ([#25827](https://github.com/MetaMask/metamask-extension/pull/25827))
-- feat: add option of copy to info row component ([#25682](https://github.com/MetaMask/metamask-extension/pull/25682))
-- fix: skip blockaid validations for users internal accounts ([#25695](https://github.com/MetaMask/metamask-extension/pull/25695))
-- chore: refactor custody component ([#25684](https://github.com/MetaMask/metamask-extension/pull/25684))
-- Merge origin/develop into master-sync
-- chore: update @metamask/bitcoin-wallet-snap to 0.2.4 ([#25808](https://github.com/MetaMask/metamask-extension/pull/25808))
-- chore: removed unused getCustodianAccountsByAddress method ([#25798](https://github.com/MetaMask/metamask-extension/pull/25798))
-- feat: Make Jest unit tests run faster in GitHub actions ([#25726](https://github.com/MetaMask/metamask-extension/pull/25726))
-- revert: un-revert metrics and signature refactor test ([#25758](https://github.com/MetaMask/metamask-extension/pull/25758))
-- feat: Add `ui_customizations` metric for transactions ([#25736](https://github.com/MetaMask/metamask-extension/pull/25736))
-- test: add e2e tests for navigation (#25652) ([#25652](https://github.com/MetaMask/metamask-extension/pull/25652))
-- chore: remove `BTC_BETA_SUPPORT` flag ([#25776](https://github.com/MetaMask/metamask-extension/pull/25776))
-- chore: update @metamask/bitcoin-wallet-snap to 0.2.3 ([#25775](https://github.com/MetaMask/metamask-extension/pull/25775))
-- feat: add more whitelisted portfolio URLs ([#25767](https://github.com/MetaMask/metamask-extension/pull/25767))
-- fix: Fix page width for fullscreen mode send page ([#25639](https://github.com/MetaMask/metamask-extension/pull/25639))
-- chore: Update Snaps codeowners list ([#25581](https://github.com/MetaMask/metamask-extension/pull/25581))
-- fix: fine-tune for `Delineator` component styles ([#25760](https://github.com/MetaMask/metamask-extension/pull/25760))
-- feat: decode transaction data ([#25597](https://github.com/MetaMask/metamask-extension/pull/25597))
-- feat: add `Delineator` component ([#25610](https://github.com/MetaMask/metamask-extension/pull/25610))
-- feat(ramps): update isNativeTokenBuyable to include BTC ([#25621](https://github.com/MetaMask/metamask-extension/pull/25621))
-- fix: Fix issue 25285 max insufficient funds for gas ([#25574](https://github.com/MetaMask/metamask-extension/pull/25574))
-- feat: add BTC experimental toggle ([#25672](https://github.com/MetaMask/metamask-extension/pull/25672))
-- build: bump gas-fee-controller to v18 and remove patch ([#25679](https://github.com/MetaMask/metamask-extension/pull/25679))
-- fix: show correct asset and balance when BTC account is the selected account ([#25719](https://github.com/MetaMask/metamask-extension/pull/25719))
-- feat(btc): add BTC account creation menu entry ([#25625](https://github.com/MetaMask/metamask-extension/pull/25625))
-- fix: flaky test `Test Snap Metrics test snap update rejected metric` ([#25744](https://github.com/MetaMask/metamask-extension/pull/25744))
-- chore(deps): bump @metamask/accounts-controller from ^17.0.0 to ^17.2.0 ([#25676](https://github.com/MetaMask/metamask-extension/pull/25676))
-- fix: use LAVAMOAT_UPDATE_TOKEN in attributions workflow ([#25731](https://github.com/MetaMask/metamask-extension/pull/25731))
-- fix: caveat mutations for non-EVM accounts ([#25739](https://github.com/MetaMask/metamask-extension/pull/25739))
-- test: Add UI integration tests ([#24428](https://github.com/MetaMask/metamask-extension/pull/24428))
-- fix: revert "test: add e2e tests for navigation (#25652)" ([#25652](https://github.com/MetaMask/metamask-extension/pull/25652))
-- chore: Revert "test: e2e metrics test and refactor" ([#25722](https://github.com/MetaMask/metamask-extension/pull/25722))
-- feat: bundle pre-installed Bitcoin Wallet Snap ([#25715](https://github.com/MetaMask/metamask-extension/pull/25715))
-- fix: protect against phishing domain redirects in main/sub frames for http(s) requests ([#25153](https://github.com/MetaMask/metamask-extension/pull/25153))
-- fix: Fix crash of Transaction screen with smart transaction ([#25717](https://github.com/MetaMask/metamask-extension/pull/25717))
-- fix: Hide MMI Account Mistmatch BannerAlert from Sign-in with Ethereum (SIWE) Redesign Page ([#25662](https://github.com/MetaMask/metamask-extension/pull/25662))
-- fix: flaky test `Create token, approve token and approve token without gas approves an already created token and displays the token approval data` ([#25706](https://github.com/MetaMask/metamask-extension/pull/25706))
-- feat: Enable SIWE Signature Redesign ([#25660](https://github.com/MetaMask/metamask-extension/pull/25660))
-- fix: flaky test `Request-queue UI changes handles three confirmations on three confirmations concurrently` ([#25675](https://github.com/MetaMask/metamask-extension/pull/25675))
-- feat: move unit tests from Circleci to Github actions ([#25570](https://github.com/MetaMask/metamask-extension/pull/25570))
-- test: e2e metrics test and refactor ([#25632](https://github.com/MetaMask/metamask-extension/pull/25632))
-- test: add e2e tests for navigation ([#25652](https://github.com/MetaMask/metamask-extension/pull/25652))
-- feat: support security alerts API ([#25544](https://github.com/MetaMask/metamask-extension/pull/25544))
-- feat(ramps): add flag to ensure ramp networks are only fetched once ([#25686](https://github.com/MetaMask/metamask-extension/pull/25686))
-- fix: allow ramps dev environment on Flask ([#25659](https://github.com/MetaMask/metamask-extension/pull/25659))
-- feat: added check for if the selected account is BTC in transaction-list ([#25642](https://github.com/MetaMask/metamask-extension/pull/25642))
-- feat: Gas Fees Redesign PoC ([#24714](https://github.com/MetaMask/metamask-extension/pull/24714))
-- fix: show connected toast only for EVM accounts ([#25628](https://github.com/MetaMask/metamask-extension/pull/25628))
-- fix: changed logic to use the new banner alert ([#25626](https://github.com/MetaMask/metamask-extension/pull/25626))
-- fix: set network client id for domain ([#25646](https://github.com/MetaMask/metamask-extension/pull/25646))
-- feat: improvement for how we display big and small numbers ([#25438](https://github.com/MetaMask/metamask-extension/pull/25438))
-- chore: restore bot workflow to update attributions ([#25211](https://github.com/MetaMask/metamask-extension/pull/25211))
-- test: add swap e2e tests on Tenderly network ([#25060](https://github.com/MetaMask/metamask-extension/pull/25060))
-- fix: UX: Multichain: Add safeguard to throw error when confirmation chainId doesn't match current chainId ([#25634](https://github.com/MetaMask/metamask-extension/pull/25634))
-- chore: updates MMI custody controller ([#25631](https://github.com/MetaMask/metamask-extension/pull/25631))
-- fix: flaky test `Test Snap Get Locale test snap_getLocale functionality` ([#25648](https://github.com/MetaMask/metamask-extension/pull/25648))
-- fix: Skip blockaid validation for SIWE signature types ([#25612](https://github.com/MetaMask/metamask-extension/pull/25612))
-- feat: Add support for security alerts on zkSync, Berachain, Scroll and Metachain One on extension ([#25555](https://github.com/MetaMask/metamask-extension/pull/25555))
-- fix: Multichain: UX: Check for transactions on all networks and QueuedRequestCount ([#25614](https://github.com/MetaMask/metamask-extension/pull/25614))
-- feat: define which keyring methods Portfolio can call ([#25633](https://github.com/MetaMask/metamask-extension/pull/25633))
-- chore: flaky E2E tests improved ([#25565](https://github.com/MetaMask/metamask-extension/pull/25565))
-- feat: add SIWE mismatch account warning alert ([#25613](https://github.com/MetaMask/metamask-extension/pull/25613))
-- fix: support multichain in blockexplorer and qr code ([#25526](https://github.com/MetaMask/metamask-extension/pull/25526))
-- fix: decimal places displayed on token value on permit pages ([#25410](https://github.com/MetaMask/metamask-extension/pull/25410))
-- feat: added BTC variant to ramps-card and illustration image ([#25615](https://github.com/MetaMask/metamask-extension/pull/25615))
-- fix: Remove unused fixtures and fix test name in smart swaps disabled spec ([#25616](https://github.com/MetaMask/metamask-extension/pull/25616))
-- chore: Update @metamask/smart-transactions-controller from 10.1.2 to 10.1.6 ([#25611](https://github.com/MetaMask/metamask-extension/pull/25611))
-- fix: Fix issue 22837 about unknown error during ledger pair ([#25462](https://github.com/MetaMask/metamask-extension/pull/25462))
-- test: add e2e to swap with snap account ([#25558](https://github.com/MetaMask/metamask-extension/pull/25558))
-- chore: exclude running git diff job for the e2e quality gate in `develop`, `master` and release branches ([#25605](https://github.com/MetaMask/metamask-extension/pull/25605))
-- chore: [Delivery] Update author mapping list for PR ([#25606](https://github.com/MetaMask/metamask-extension/pull/25606))
-- fix: page object selector not found ([#25624](https://github.com/MetaMask/metamask-extension/pull/25624))
-- test: Initial PR for integrating the Page Object Model (POM) into e2e test suite ([#25373](https://github.com/MetaMask/metamask-extension/pull/25373))
-- refactor: Replace deprecated mixins with Text component in selected-account.component.js ([#25262](https://github.com/MetaMask/metamask-extension/pull/25262))
-- refactor: Replace deprecated mixins with Text component in unlock-page.component.js ([#25227](https://github.com/MetaMask/metamask-extension/pull/25227))
-- chore: Create a story for RestoreVaultPage component ([#25284](https://github.com/MetaMask/metamask-extension/pull/25284))
-- fix(snaps): Fix alignment of install origin is `snap-authorship-expanded` ([#25583](https://github.com/MetaMask/metamask-extension/pull/25583))
-- feat: Remove blockaid migration BannerAlert ([#25556](https://github.com/MetaMask/metamask-extension/pull/25556))
-- fix: failingt e2e `Click bridge button from asset page @no-mmi loads portfolio tab when flag is turned off` ([#25607](https://github.com/MetaMask/metamask-extension/pull/25607))
-- chore: adds quality gate for rerunning e2e spec files that are new or have been modified ([#24556](https://github.com/MetaMask/metamask-extension/pull/24556))
-- chore(deps): bump assets controller to v34.0.0 ([#25540](https://github.com/MetaMask/metamask-extension/pull/25540))
-- chore: add bridge controller, store and api utils ([#25044](https://github.com/MetaMask/metamask-extension/pull/25044))
-- fix: add eth_signTypedData and eth_signTypedData_v3 to `methodsRequiringNetworkSwitch` ([#25562](https://github.com/MetaMask/metamask-extension/pull/25562))
+### Added
+- Added the ability to name accounts during the snap account creation flow ([#25191](https://github.com/MetaMask/metamask-extension/pull/25191))
+- Added an experimental settings toggle for the transactions redesign ([#26010](https://github.com/MetaMask/metamask-extension/pull/26010))
+- Added a banner alert to help users manage queued transactions from different dApps ([#25852](https://github.com/MetaMask/metamask-extension/pull/25852))
+- Add "See all permissions" button to Snaps permissions view, and improve scrolling behaviour ([#25175](https://github.com/MetaMask/metamask-extension/pull/25175))
+- Added redesigned UI and new UX for the Snap home page and Snap dialog, including a full screen view and an updated Snap Authorship header ([#25670](https://github.com/MetaMask/metamask-extension/pull/25670))
+- Enabled hardware wallets for smart transactions in MetaMask swaps ([#25742](https://github.com/MetaMask/metamask-extension/pull/25742))
+- Added a "Close extension" button on the Smart Transaction Status Page for pending dapp transactions ([#25965](https://github.com/MetaMask/metamask-extension/pull/25965))
+- Added a toast message to notify users if they quickly send transactions on different networks ([#26114](https://github.com/MetaMask/metamask-extension/pull/26114))
+- Enabled token auto-detection by default ([#26406](https://github.com/MetaMask/metamask-extension/pull/26406))
+
+### Changed
+- Improve information and presentation of permit signatures, including: PermitSingle, PermitBatch, PermitTransferFrom, PermitBatchTransferFrom and TradeOrder ([#26107](https://github.com/MetaMask/metamask-extension/pull/26107))
+- Updated the design for the NFT details page ([#25524](https://github.com/MetaMask/metamask-extension/pull/25524))
+- Updated the Bitcoin account creation flow to use the new Snap account creation process, including account renaming ([#26183](https://github.com/MetaMask/metamask-extension/pull/26183))
+- Removed the mention of password managers from the Secret Recovery Phrase onboarding instructions and reordered the bullet points ([#25985](https://github.com/MetaMask/metamask-extension/pull/25985))
+- Updated the BNB network logos ([#26140](https://github.com/MetaMask/metamask-extension/pull/26140))
+- Removed support for the eth_sign method ([#24756](https://github.com/MetaMask/metamask-extension/pull/24756))
+- Updated the dApp permission screen for network switching requests ([#25703](https://github.com/MetaMask/metamask-extension/pull/25703))
+- Updated the STX Opt In modal to replace "Manage in settings" with "No thanks" and only show the modal for non-zero balances ([#25848](https://github.com/MetaMask/metamask-extension/pull/25848))
+- Displayed advanced details by default in confirmations for users with nonce editing or hex data enabled ([#25687](https://github.com/MetaMask/metamask-extension/pull/25687))
+- Enhanced the performance of the account list to make it faster and more responsive ([#26379](https://github.com/MetaMask/metamask-extension/pull/26379))
+- Updated logos for Flare Mainnet and Songbird ([#25560](https://github.com/MetaMask/metamask-extension/pull/25560))
+- Updated various icons to improve visual consistency ([#26180](https://github.com/MetaMask/metamask-extension/pull/26180))
+- Added a popover to truncate and display long NFT token IDs ([#26179](https://github.com/MetaMask/metamask-extension/pull/26179))
+- Removed the halo around token avatars ([#26016](https://github.com/MetaMask/metamask-extension/pull/26016))
+- Improved the alignment of token icons to be centered in the token list ([#26013](https://github.com/MetaMask/metamask-extension/pull/26013))
+- Improved the display of "data unavailable" text and contract addresses on the NFT details page ([#25931](https://github.com/MetaMask/metamask-extension/pull/25931))
+- Improved the warning message in the add network modal ([#26250](https://github.com/MetaMask/metamask-extension/pull/26250))
+- Improved performance for large signature request confirmations ([#26209](https://github.com/MetaMask/metamask-extension/pull/26209))
+- Updated the pending transactions badge to display a number instead of three dots ([#26116](https://github.com/MetaMask/metamask-extension/pull/26116))
+- Added a link to the Metametrics page in the onboarding flow to explain data management and profile syncing ([#26038](https://github.com/MetaMask/metamask-extension/pull/26038))
+- Improved the AccountListMenu to hide the back button by default, showing it only when needed ([#27152](https://github.com/MetaMask/metamask-extension/pull/27152))
+
+### Fixed
+- Fixed an issue where the wallet was not accessible with a new password after resetting it ([#25847](https://github.com/MetaMask/metamask-extension/pull/25847))
+- Fixed number formatting for swap + send transaction details to avoid scientific notation for small token amounts ([#26029](https://github.com/MetaMask/metamask-extension/pull/26029))
+- Fixed an issue with link redirection to ensure proper navigation ([#25983](https://github.com/MetaMask/metamask-extension/pull/25983))
+- Fixed the issue of overlapping modals ([#25962](https://github.com/MetaMask/metamask-extension/pull/25962))
+- Fixed the issue where pressing the Enter key on the Create Account checkbox would trigger show/hide password ([#26394](https://github.com/MetaMask/metamask-extension/pull/26394))
+- Fixed the logic to correctly fetch token decimals for permit and order signatures ([#26292](https://github.com/MetaMask/metamask-extension/pull/26292))
+- Fixed an issue to prevent automatic reconnection to previously unlocked hardware wallets ([#25503](https://github.com/MetaMask/metamask-extension/pull/25503))
+- Updated the text in the popup to inform users about managing notifications in the settings ([#26026](https://github.com/MetaMask/metamask-extension/pull/26026))
+- Fixed UI issues with displaying website URLs in the Snaps permissions interface ([#26422](https://github.com/MetaMask/metamask-extension/pull/26422))
+- Fixed an issue to prevent unnecessary errors when setting network client IDs for domains without account permissions ([#26323](https://github.com/MetaMask/metamask-extension/pull/26323))
+- Fixed an issue by clearing invalid network settings to prevent errors and improve stability ([#26428](https://github.com/MetaMask/metamask-extension/pull/26428))
+- Fixed the issue where the "Switch to this account" option was not showing for single connected accounts on the connections page ([#25609](https://github.com/MetaMask/metamask-extension/pull/25609))
+- Fixed the max width of the permissions page to match other screens in full screen view ([#25870](https://github.com/MetaMask/metamask-extension/pull/25870))
+- Fixed the issue to show the current network when domains are undefined ([#25960](https://github.com/MetaMask/metamask-extension/pull/25960))
+- Fixed the estimated fee calculation in redesigned screens by converting fee values to the correct units ([#27250](https://github.com/MetaMask/metamask-extension/pull/27250))
+- Fixed an issue to allow re-submitting a cancelled swap if it was cancelled via a hardware wallet ([#27210](https://github.com/MetaMask/metamask-extension/pull/27210))
+- Fixed an issue that caused MetaMask to crash when certain permit values were not loaded ([#26791](https://github.com/MetaMask/metamask-extension/pull/26791))
+- Fixed an issue where the "Add a new Bitcoin account (testnet)" option was repeated ([#27116](https://github.com/MetaMask/metamask-extension/pull/27116))
## [12.2.4]
### Fixed
@@ -480,7 +177,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed fallback conversion rates for token market data to ensure accurate market cap ([#26460](https://github.com/MetaMask/metamask-extension/pull/26460))
- Resolved the issue of selecting the correct network when multiple networks have the same chain ID ([#25805](https://github.com/MetaMask/metamask-extension/pull/25805))
- Updated alignment and padding for permit simulations ([#26186](https://github.com/MetaMask/metamask-extension/pull/26186))
-- Updated the pending transactions badge to display a number instead of three dots ([#26116](https://github.com/MetaMask/metamask-extension/pull/26116))
- Adjusted spacing in the send asset picker for proper vertical alignment with other dropdowns ([#25576](https://github.com/MetaMask/metamask-extension/pull/25576))
- Fixed decimal display for Permit values and added a reusable component for displaying token units ([#26105](https://github.com/MetaMask/metamask-extension/pull/26105))
- Fixed precision loss for very large values in signature simulations ([#25968](https://github.com/MetaMask/metamask-extension/pull/25968))