|
1 | 1 | /* eslint-disable import-x/no-commonjs */ |
| 2 | + |
| 3 | +/** |
| 4 | + * Files still allowed to import deprecated `app/util/number/index.js` during |
| 5 | + * the BN.js → BigInt migration. Kept in one array so the default import-fence |
| 6 | + * override can exclude them while the follow-up override below re-applies only |
| 7 | + * the expo-haptics / perps restrictions (see comments on those overrides). |
| 8 | + */ |
| 9 | +const utilNumberImportBurndownFiles = [ |
| 10 | + 'app/component-library/components-temp/CustomSpendCap/CustomInput/CustomInput.tsx', |
| 11 | + 'app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx', |
| 12 | + 'app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.tsx', |
| 13 | + 'app/component-library/components-temp/Price/AggregatedPercentage/utils.ts', |
| 14 | + 'app/components/UI/AccountInfoCard/index.js', |
| 15 | + 'app/components/UI/AssetOverview/Price/Price.advanced.tsx', |
| 16 | + 'app/components/UI/AssetOverview/Price/Price.legacy.tsx', |
| 17 | + 'app/components/UI/AssetOverview/utils/marketDetails.ts', |
| 18 | + 'app/components/UI/Bridge/components/QuoteSelectorView/QuoteRow.tsx', |
| 19 | + 'app/components/UI/Bridge/components/QuoteSelectorView/index.tsx', |
| 20 | + 'app/components/UI/Bridge/hooks/useBridgeQuoteData/index.ts', |
| 21 | + 'app/components/UI/Bridge/hooks/useFormattedBalanceWithThreshold/index.ts', |
| 22 | + 'app/components/UI/Bridge/hooks/useHasSufficientGas/index.ts', |
| 23 | + 'app/components/UI/Bridge/hooks/useInsufficientBalance/index.ts', |
| 24 | + 'app/components/UI/Bridge/hooks/useTokenBalanceInUsd/index.ts', |
| 25 | + 'app/components/UI/Bridge/hooks/useTokensWithBalance/index.ts', |
| 26 | + 'app/components/UI/Bridge/utils/exchange-rates.ts', |
| 27 | + 'app/components/UI/Bridge/utils/formatNetworkFee.test.ts', |
| 28 | + 'app/components/UI/Bridge/utils/formatNetworkFee.ts', |
| 29 | + 'app/components/UI/Bridge/utils/transaction-history.ts', |
| 30 | + 'app/components/UI/Card/hooks/useAssetBalances.tsx', |
| 31 | + 'app/components/UI/Card/hooks/useCardDelegation.test.ts', |
| 32 | + 'app/components/UI/Card/hooks/useCardDelegation.ts', |
| 33 | + 'app/components/UI/Card/hooks/useNeedsGasFaucet.ts', |
| 34 | + 'app/components/UI/Card/sdk/CardSDK.ts', |
| 35 | + 'app/components/UI/CollectibleOverview/index.js', |
| 36 | + 'app/components/UI/Earn/Views/EarnInputView/EarnInputView.test.tsx', |
| 37 | + 'app/components/UI/Earn/Views/EarnLendingDepositConfirmationView/components/Erc20TokenHero/index.tsx', |
| 38 | + 'app/components/UI/Earn/Views/EarnLendingDepositConfirmationView/index.tsx', |
| 39 | + 'app/components/UI/Earn/Views/EarnLendingWithdrawalConfirmationView/index.tsx', |
| 40 | + 'app/components/UI/Earn/Views/EarnWithdrawInputView/EarnWithdrawInputView.tsx', |
| 41 | + 'app/components/UI/Earn/components/EarnLendingBalance/index.tsx', |
| 42 | + 'app/components/UI/Earn/components/Earnings/EarningsHistory/EarningsHistory.utils.ts', |
| 43 | + 'app/components/UI/Earn/components/InputDisplay/InputDisplay.test.tsx', |
| 44 | + 'app/components/UI/Earn/hooks/useEarnGasFee.ts', |
| 45 | + 'app/components/UI/Earn/hooks/useEarnInput.ts', |
| 46 | + 'app/components/UI/Earn/hooks/useEarnings.ts', |
| 47 | + 'app/components/UI/Earn/hooks/useInput.ts', |
| 48 | + 'app/components/UI/Earn/hooks/useMultichainInputHandlers.ts', |
| 49 | + 'app/components/UI/Earn/hooks/useMusdBalance.ts', |
| 50 | + 'app/components/UI/Earn/hooks/useMusdCtaVisibility.ts', |
| 51 | + 'app/components/UI/Earn/utils/number.ts', |
| 52 | + 'app/components/UI/Earn/utils/token/index.ts', |
| 53 | + 'app/components/UI/Earn/utils/tron.ts', |
| 54 | + 'app/components/UI/HardwareWallet/AccountDetails/index.tsx', |
| 55 | + 'app/components/UI/Money/constants/activityStyles.ts', |
| 56 | + 'app/components/UI/Money/hooks/useMoneyAccountBalance.ts', |
| 57 | + 'app/components/UI/Money/utils/moneyActivityFiat.ts', |
| 58 | + 'app/components/UI/MultichainBridgeTransactionListItem/MultichainBridgeTransactionListItem.tsx', |
| 59 | + 'app/components/UI/Notification/TransactionNotification/index.js', |
| 60 | + 'app/components/UI/Ramp/Aggregator/Views/BuildQuote/BuildQuote.test.tsx', |
| 61 | + 'app/components/UI/Ramp/Aggregator/Views/BuildQuote/BuildQuote.tsx', |
| 62 | + 'app/components/UI/Ramp/Aggregator/Views/OrdersList/OrdersList.tsx', |
| 63 | + 'app/components/UI/Ramp/Aggregator/Views/SendTransaction/SendTransaction.tsx', |
| 64 | + 'app/components/UI/Ramp/Aggregator/components/OrderDetails.tsx', |
| 65 | + 'app/components/UI/Ramp/Aggregator/components/OrderListItem/OrderListItem.tsx', |
| 66 | + 'app/components/UI/Ramp/Aggregator/components/Quote/Quote.tsx', |
| 67 | + 'app/components/UI/Ramp/Aggregator/hooks/useBalance.test.ts', |
| 68 | + 'app/components/UI/Ramp/Aggregator/hooks/useBalance.ts', |
| 69 | + 'app/components/UI/Ramp/Aggregator/hooks/useERC20GasLimitEstimation.ts', |
| 70 | + 'app/components/UI/Ramp/Aggregator/hooks/useHandleSuccessfulOrder.ts', |
| 71 | + 'app/components/UI/Ramp/Aggregator/hooks/useIntentAmount.ts', |
| 72 | + 'app/components/UI/Ramp/Aggregator/utils/index.ts', |
| 73 | + 'app/components/UI/Ramp/Deposit/utils/index.ts', |
| 74 | + 'app/components/UI/Ramp/utils/getOrderAmount.ts', |
| 75 | + 'app/components/UI/Ramp/utils/v2OrderToast.ts', |
| 76 | + 'app/components/UI/Stake/components/StakingBalance/StakingBanners/ClaimBanner/ClaimBanner.tsx', |
| 77 | + 'app/components/UI/Stake/components/StakingConfirmation/TokenValueStack/TokenValueStack.test.tsx', |
| 78 | + 'app/components/UI/Stake/components/StakingConfirmation/TokenValueStack/TokenValueStack.tsx', |
| 79 | + 'app/components/UI/Stake/components/StakingConfirmation/YouReceiveCard/YouReceiveCard.test.tsx', |
| 80 | + 'app/components/UI/Stake/components/StakingConfirmation/YouReceiveCard/YouReceiveCard.tsx', |
| 81 | + 'app/components/UI/Stake/hooks/useBalance.ts', |
| 82 | + 'app/components/UI/Tokens/util/deriveBalanceFromAssetMarketDetails.test.ts', |
| 83 | + 'app/components/UI/Tokens/util/deriveBalanceFromAssetMarketDetails.ts', |
| 84 | + 'app/components/UI/TransactionElement/utils-gas.js', |
| 85 | + 'app/components/UI/TransactionElement/utils.js', |
| 86 | + 'app/components/UI/UrlAutocomplete/Result.tsx', |
| 87 | + 'app/components/Views/AssetDetails/index.tsx', |
| 88 | + 'app/components/Views/DetectedTokens/components/Token.tsx', |
| 89 | + 'app/components/Views/GasEducationCarousel/index.js', |
| 90 | + 'app/components/Views/NetworksManagement/NetworkDetailsView/hooks/useNetworkValidation.ts', |
| 91 | + 'app/components/Views/SocialLeaderboard/TraderPositionView/components/QuickBuyBottomSheet/useQuickBuyBottomSheet.ts', |
| 92 | + 'app/components/Views/SocialLeaderboard/TraderPositionView/components/QuickBuyBottomSheet/useQuickBuyQuotes.ts', |
| 93 | + 'app/components/Views/SocialLeaderboard/utils/formatters.ts', |
| 94 | + 'app/components/Views/UnifiedTransactionsView/useUnifiedTxActions.test.ts', |
| 95 | + 'app/components/Views/confirmations/components/gas/max-base-fee-input/max-base-fee-input.tsx', |
| 96 | + 'app/components/Views/confirmations/components/gas/priority-fee-input/priority-fee-input.tsx', |
| 97 | + 'app/components/Views/confirmations/components/info/typed-sign-v3v4/simulation/components/native-value-display/native-value-display.tsx', |
| 98 | + 'app/components/Views/confirmations/components/info/typed-sign-v3v4/simulation/components/value-display/value-display.tsx', |
| 99 | + 'app/components/Views/confirmations/components/transactions/custom-amount/custom-amount.tsx', |
| 100 | + 'app/components/Views/confirmations/context/send-context/utils.ts', |
| 101 | + 'app/components/Views/confirmations/external/staking/hooks/useStakingDetails.ts', |
| 102 | + 'app/components/Views/confirmations/hooks/earn/useCustomAmount.tsx', |
| 103 | + 'app/components/Views/confirmations/hooks/gas/useCancelSpeedupGas/useCancelSpeedupGas.ts', |
| 104 | + 'app/components/Views/confirmations/hooks/send/useBalance.ts', |
| 105 | + 'app/components/Views/confirmations/hooks/send/useCurrencyConversions.ts', |
| 106 | + 'app/components/Views/confirmations/hooks/send/usePercentageAmount.ts', |
| 107 | + 'app/components/Views/confirmations/hooks/useTokenAmount.ts', |
| 108 | + 'app/components/Views/confirmations/legacy/components/CustomNonceModal/index.js', |
| 109 | + 'app/components/Views/confirmations/legacy/components/WatchAssetRequest/index.js', |
| 110 | + 'app/components/Views/confirmations/utils/send.ts', |
| 111 | + 'app/components/hooks/useAddressBalance/useAddressBalance.ts', |
| 112 | + 'app/components/hooks/useGetFormattedTokensPerChain.tsx', |
| 113 | + 'app/components/hooks/useGetTotalFiatBalanceCrossChains.tsx', |
| 114 | + 'app/core/Engine/Engine.ts', |
| 115 | + 'app/core/Engine/controllers/gas-fee-controller/gas-fee-controller-init.test.ts', |
| 116 | + 'app/core/GasPolling/GasPolling.ts', |
| 117 | + 'app/core/NotificationManager.js', |
| 118 | + 'app/selectors/assets/assets-list.ts', |
| 119 | + 'app/selectors/earnController/earn/index.ts', |
| 120 | + 'app/selectors/multichain/evm.ts', |
| 121 | + // `app/util/**` importers of `./number` or `../number` (resolves to `index.js`); |
| 122 | + // same burndown contract as feature files — remove when migrated to |
| 123 | + // `../number/bigint` (or `./number/bigint` from `app/util/`). |
| 124 | + 'app/util/confirm-tx.js', |
| 125 | + 'app/util/conversions.js', |
| 126 | + 'app/util/confirmation/gas.ts', |
| 127 | + 'app/util/confirmation/transactions.ts', |
| 128 | + 'app/util/custom-gas/index.js', |
| 129 | + 'app/util/networks/index.js', |
| 130 | + 'app/util/transactions/index.js', |
| 131 | + 'app/util/transactions/index.test.ts', |
| 132 | +]; |
| 133 | + |
2 | 134 | module.exports = { |
3 | 135 | root: true, |
4 | 136 | parser: '@typescript-eslint/parser', |
@@ -42,6 +174,11 @@ module.exports = { |
42 | 174 | 'interface', |
43 | 175 | ], |
44 | 176 | '@typescript-eslint/no-explicit-any': 'error', |
| 177 | + // Surface JSDoc @deprecated annotations at every use-site (warn for now; |
| 178 | + // ratchet to 'error' once the BN.js → BigInt migration is complete). |
| 179 | + // Pairs with the `import-x/no-restricted-paths` fence on |
| 180 | + // `app/util/number/index.js` in the app import-fence override below. |
| 181 | + '@typescript-eslint/no-deprecated': 'warn', |
45 | 182 | // Under discussion |
46 | 183 | '@typescript-eslint/no-duplicate-enum-values': 'off', |
47 | 184 | '@typescript-eslint/no-shadow': [ |
@@ -248,6 +385,33 @@ module.exports = { |
248 | 385 | ], |
249 | 386 | }, |
250 | 387 | }, |
| 388 | + { |
| 389 | + files: ['**/*.test.{js,ts,tsx,jsx}', '**/*.spec.{js,ts,tsx,jsx}'], |
| 390 | + plugins: ['jest'], |
| 391 | + rules: { |
| 392 | + // Prevent new file-based snapshots. Inline snapshots (toMatchInlineSnapshot) |
| 393 | + // are still allowed as they keep assertions co-located with the test. |
| 394 | + 'jest/no-restricted-matchers': [ |
| 395 | + 'error', |
| 396 | + { |
| 397 | + toMatchSnapshot: |
| 398 | + 'Use toMatchInlineSnapshot() or an explicit assertion instead. File-based snapshots are being phased out.', |
| 399 | + }, |
| 400 | + ], |
| 401 | + }, |
| 402 | + }, |
| 403 | + { |
| 404 | + // Matches CODEOWNERS `**/snaps/**` and `**/Snaps/**` (@MetaMask/core-platform). |
| 405 | + // ESLint cannot read CODEOWNERS. |
| 406 | + files: [ |
| 407 | + '**/snaps/**/*.{test,spec}.{js,ts,tsx,jsx}', |
| 408 | + '**/Snaps/**/*.{test,spec}.{js,ts,tsx,jsx}', |
| 409 | + ], |
| 410 | + plugins: ['jest'], |
| 411 | + rules: { |
| 412 | + 'jest/no-restricted-matchers': 'off', |
| 413 | + }, |
| 414 | + }, |
251 | 415 | // ── Perps controller Core-alignment override ── |
252 | 416 | // Enforces the same ESLint rules that Core's @metamask/eslint-config |
253 | 417 | // applies to packages/perps-controller so that code written in mobile |
@@ -466,18 +630,100 @@ module.exports = { |
466 | 630 | }, |
467 | 631 | }, |
468 | 632 | { |
469 | | - files: ['app/**/*.{ts,tsx}'], |
470 | | - excludedFiles: ['app/controllers/perps/**/*.{ts,tsx}'], |
| 633 | + // Default app import fences (expo-haptics, perps, deprecated util/number/index.js). |
| 634 | + // `excludedFiles` applies to the whole override — listing burn-down paths |
| 635 | + // here would incorrectly skip expo/perps for those files, so burn-down is |
| 636 | + // excluded from *this* block only and picked up by the next override. |
| 637 | + files: ['app/**/*.{ts,tsx,js,jsx}'], |
| 638 | + excludedFiles: [ |
| 639 | + // Perps controller is exempt from importing itself. |
| 640 | + 'app/controllers/perps/**/*.{ts,tsx,js,jsx}', |
| 641 | + // Designated expo-haptics wrapper — only this tree may import expo-haptics. |
| 642 | + 'app/util/haptics/**/*.{ts,tsx,js,jsx}', |
| 643 | + // Legacy number utils + parity tests. |
| 644 | + 'app/util/number/**', |
| 645 | + // BN.js → BigInt burn-down: still allowed util/number imports; see next override. |
| 646 | + ...utilNumberImportBurndownFiles, |
| 647 | + ], |
| 648 | + rules: { |
| 649 | + 'no-restricted-imports': [ |
| 650 | + 'error', |
| 651 | + { |
| 652 | + paths: [ |
| 653 | + { |
| 654 | + name: 'expo-haptics', |
| 655 | + message: |
| 656 | + 'Import from app/util/haptics instead of expo-haptics directly.', |
| 657 | + }, |
| 658 | + ], |
| 659 | + patterns: [ |
| 660 | + { |
| 661 | + group: ['**/controllers/perps', '**/controllers/perps/**'], |
| 662 | + message: |
| 663 | + 'Use @metamask/perps-controller instead of relative imports into app/controllers/perps/.', |
| 664 | + }, |
| 665 | + { |
| 666 | + group: ['expo-haptics/*'], |
| 667 | + message: |
| 668 | + 'Import from app/util/haptics instead of expo-haptics directly.', |
| 669 | + }, |
| 670 | + ], |
| 671 | + }, |
| 672 | + ], |
| 673 | + // Fences the deprecated `app/util/number/index.js` module. We use |
| 674 | + // `import-x/no-restricted-paths` (not `no-restricted-imports`) because |
| 675 | + // it resolves each import to its absolute file, which means a single |
| 676 | + // entry catches every spelling that lands on `index.js` — bare |
| 677 | + // (`from '../util/number'`), explicit (`'../util/number/index'`), |
| 678 | + // and explicit-with-extension. Sibling modules like `bigint`, |
| 679 | + // `bignumber`, and `subscriptNotation` resolve to different files |
| 680 | + // and are unaffected, so no negation list is needed. Inherits the |
| 681 | + // burn-down allowlist from this override's `excludedFiles`; the |
| 682 | + // burn-down override below intentionally does not re-declare this |
| 683 | + // rule, so allow-listed files remain exempt. |
| 684 | + 'import-x/no-restricted-paths': [ |
| 685 | + 'error', |
| 686 | + { |
| 687 | + zones: [ |
| 688 | + { |
| 689 | + target: 'app', |
| 690 | + from: 'app/util/number/index.js', |
| 691 | + message: |
| 692 | + 'app/util/number/index.js is deprecated. Import the BigInt-based replacement from app/util/number/bigint instead. See app/util/number/bigint-migration-reference.test.ts for migration patterns.', |
| 693 | + }, |
| 694 | + ], |
| 695 | + }, |
| 696 | + ], |
| 697 | + }, |
| 698 | + }, |
| 699 | + { |
| 700 | + // Re-apply expo-haptics + perps only for burn-down files. A second |
| 701 | + // override is required because ESLint replaces `no-restricted-imports` |
| 702 | + // when the same rule is set again — we cannot use one override with only |
| 703 | + // `excludedFiles` for util/number without silently dropping other fences. |
| 704 | + files: utilNumberImportBurndownFiles, |
471 | 705 | rules: { |
472 | 706 | 'no-restricted-imports': [ |
473 | 707 | 'error', |
474 | 708 | { |
| 709 | + paths: [ |
| 710 | + { |
| 711 | + name: 'expo-haptics', |
| 712 | + message: |
| 713 | + 'Import from app/util/haptics instead of expo-haptics directly.', |
| 714 | + }, |
| 715 | + ], |
475 | 716 | patterns: [ |
476 | 717 | { |
477 | 718 | group: ['**/controllers/perps', '**/controllers/perps/**'], |
478 | 719 | message: |
479 | 720 | 'Use @metamask/perps-controller instead of relative imports into app/controllers/perps/.', |
480 | 721 | }, |
| 722 | + { |
| 723 | + group: ['expo-haptics/*'], |
| 724 | + message: |
| 725 | + 'Import from app/util/haptics instead of expo-haptics directly.', |
| 726 | + }, |
481 | 727 | ], |
482 | 728 | }, |
483 | 729 | ], |
|
0 commit comments