Skip to content

Comments

Feat/restricted popup#771

Merged
kvhnuke merged 11 commits intofeat/provider-namesfrom
feat/restricted-popup
Nov 27, 2025
Merged

Feat/restricted popup#771
kvhnuke merged 11 commits intofeat/provider-namesfrom
feat/restricted-popup

Conversation

@gamalielhere
Copy link
Contributor

@gamalielhere gamalielhere commented Nov 24, 2025

Summary by CodeRabbit

Release Notes v2.14.0

  • New Features

    • Added Nibiru and Nibiru Testnet network support
    • Implemented restricted address detection with geographic restrictions handling
    • Added recovery phrase view for restricted addresses
    • Enhanced swap interface with provider icons and names
  • Improvements

    • Updated network endpoints to community-managed servers
    • Improved address validation logic
  • Removals

    • Discontinued support for Canto, ZChains, and ProofOfPlayApex networks
  • Bug Fixes

    • Fixed transaction address generation in verification flow

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 24, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

🗂️ Base branches to auto review (3)
  • main
  • develop
  • devop/vite-migrate

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This PR introduces support for Nibiru/Nibiru Testnet networks with Routescan activity tracking, removes support for four networks (Canto, ZChains, ProofOfPlayApex, and Okc token handling), implements a geo-restricted user interface flow, adds provider display information to swap UI, updates Kadena endpoints to community URLs, and updates dependencies across all packages with endpoint migrations for existing networks.

Changes

Cohort / File(s) Summary
Nibiru Network Support (Addition)
packages/types/src/networks.ts, packages/extension/src/providers/ethereum/networks/nibiru.ts, packages/extension/src/providers/ethereum/networks/nibiru-testnet.ts, packages/extension/src/providers/ethereum/networks/index.ts, packages/extension/src/providers/common/libs/new-features.ts, README.md
Added new Nibiru and Nibiru Testnet networks to NetworkNames enum, CoingeckoPlatform enum; created new EVM network configuration files with Routescan activity handlers; updated network exports and new-features list.
Routescan Activity Provider (New)
packages/extension/src/providers/ethereum/libs/activity-handlers/providers/routescan/index.ts, packages/extension/src/providers/ethereum/libs/activity-handlers/providers/routescan/configs.ts, packages/extension/src/providers/ethereum/libs/activity-handlers/providers/routescan/types.ts, packages/extension/src/providers/ethereum/libs/activity-handlers/index.ts
Introduced new Routescan activity handler for fetching and decoding Ethereum transactions from Routescan API; added RoutescanTxType interface and NetworkEndpoints config for Nibiru networks.
Network Support Removal
packages/extension/src/providers/ethereum/networks/canto.ts (deleted), packages/extension/src/providers/ethereum/networks/zcd.ts (deleted), packages/extension/src/providers/ethereum/networks/pop-apex.ts (deleted), packages/extension/src/providers/ethereum/networks/index.ts, packages/types/src/networks.ts
Removed Canto, ZChains, and ProofOfPlayApex EVM network files and their exports; removed these network enum members from NetworkNames and CoingeckoPlatform.
Swap Provider Display Information
packages/swap/src/types/index.ts, packages/swap/src/configs.ts, packages/swap/src/index.ts, packages/swap/src/common/icons/index.d.ts
Added ProviderNameProper enum for display names; created PROVIDER_INFO mapping with provider icons and names; added PNG module declaration.
Swap UI Provider Info Integration
packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-list-item.vue, packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-list.vue, packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/index.vue
Updated swap offer UI to display provider icons and dynamic names using PROVIDER_INFO; added provider prop to BestOfferListItem; refactored header to show provider details.
Geo-Restricted Address UI (New Feature)
packages/extension/src/ui/action/App.vue, packages/extension/src/ui/action/views/restricted/index.vue, packages/extension/src/ui/action/views/settings/components/settings-inner-header.vue, packages/extension/src/ui/action/views/settings/views/settings-recovery/index.vue
Introduced restricted address flow with full-screen Restricted component rendering when geo-restricted; added modals for unlock and recovery phrase display; added hasBack prop to settings components for controlling back button visibility.
Asset and Ledger Support Removals
packages/extension/src/providers/ethereum/libs/assets-handlers/assetinfo-mew.ts, packages/extension/src/providers/ethereum/libs/assets-handlers/token-lists.ts, packages/extension/src/providers/ethereum/libs/assets-handlers/types/tokenbalance-mew.ts, packages/hw-wallets/src/ledger/ethereum/configs.ts
Removed asset handler support for Okc, Canto, XLayer, ProofOfPlayApex; removed Klaytn and Syscoin from Ledger supported paths.
Etherscan Activity Handler Updates
packages/extension/src/providers/ethereum/libs/activity-handlers/providers/etherscan/configs.ts
Removed ProofOfPlayApex entry from Etherscan NetworkEndpoints mapping.
Network Endpoint Migrations
packages/extension/src/providers/ethereum/networks/ftm.ts, packages/extension/src/providers/ethereum/networks/astr.ts, packages/extension/src/providers/ethereum/networks/xlayer.ts, packages/extension/src/providers/ethereum/networks/palm.ts
Updated RPC endpoints: Fantom from wss to https; Astar from BlastAPI to OnFinality; XLayer from wss to https Infura; Palm to new mainnet endpoint.
Kadena Network Updates
packages/extension/src/providers/kadena/networks/kadena.ts, packages/extension/src/providers/kadena/networks/index.ts
Updated Kadena mainnet endpoints to community URLs; removed kadenaTestnet from public exports.
Other Network Configuration Changes
packages/extension/src/providers/ethereum/networks/okc.ts, packages/extension/src/providers/ethereum/networks/story.ts
Removed assetsInfoHandler from OKC network config; updated Story chainID from 0x5EF to 0x5ea.
Swap Provider Logic Updates
packages/swap/src/providers/changelly/index.ts, packages/swap/src/providers/okx/index.ts
Added RBTC floating-rate support to Changelly with optional amount parameter in getMinMaxAmount; improved OKX token data handling with fallback for missing data.
Core Extension Updates
packages/extension/src/libs/backup-state/index.ts, packages/extension/src/libs/dapp-list/index.ts, packages/extension/src/libs/utils/initialize-wallet.ts, packages/extension/src/providers/ethereum/ui/eth-verify-transaction.vue
Added excludedSignerTypes array for backup filtering; removed Canto, ZkSyncGoerli, ZChains, ProofOfPlayApex from dapp-list; reordered KadenaNetworks import; fixed realToAddress fallback and approve() address derivation.
Dependency Updates
package.json, packages/extension/package.json, packages/extension-bridge/package.json, packages/hw-wallets/package.json, packages/keyring/package.json, packages/name-resolution/package.json, packages/request/package.json, packages/signers/*/package.json (bitcoin, ethereum, kadena, massa, polkadot), packages/storage/package.json, packages/swap/package.json, packages/types/package.json, packages/utils/package.json
Updated numerous devDependencies (ESLint ecosystem, TypeScript, @types/node, vitest, tsup, etc.) and runtime dependencies (@polkadot/, @amplitude/analytics-browser, @kadena/, @ledgerhq/, @1inch/, Pinia, Vue, vite); added eslint-plugin-import and eslint-plugin-module-resolver to select packages.
Minor Formatting and Refactoring
packages/swap/tsconfig.json, packages/extension/src/ui/action/views/lock-screen/index.vue, packages/extension/src/ui/action/views/swap/index.vue
Added PNG files to tsconfig include; condensed template formatting for lock-screen and swap views with no semantic changes; adjusted CSS padding.

Sequence Diagram(s)

sequenceDiagram
    participant App as App.vue
    participant Wallet as Wallet/Accounts
    participant Network as Network Service
    participant Restriction as Restriction Service
    participant UI as UI Component

    App->>Wallet: Get activeAccounts, inactiveAccounts
    App->>Network: Get current network
    App->>Restriction: checkAddresses(accounts, network)
    Restriction->>Restriction: Query per-address restriction status
    Restriction-->>App: foundRestrictedAddress, geoRestricted
    
    alt Restricted Address or Geo-Restricted
        App->>UI: Render Restricted component (full-screen)
        UI->>UI: Show access restricted message
        UI->>UI: Show recovery phrase option
    else Not Restricted
        App->>UI: Render normal app flow
        UI->>UI: Show menu, header, network menu
        UI->>UI: Render router-view content
    end
Loading
sequenceDiagram
    participant SwapUI as Swap Best Offer UI
    participant BestOfferList as BestOfferListItem
    participant SwapConfig as Configs (PROVIDER_INFO)
    participant UI as UI Render

    SwapUI->>SwapUI: Fetch offers with trade.provider
    SwapUI->>BestOfferList: Pass provider prop and trade data
    BestOfferList->>SwapConfig: Look up PROVIDER_INFO[provider]
    SwapConfig-->>BestOfferList: Return name + icon
    BestOfferList->>UI: Render provider icon (20x20)
    BestOfferList->>UI: Render provider name (dynamic lookup)
    UI-->>SwapUI: Display offer with provider info
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Primary areas requiring extra attention:
    • Restricted address UI flow (packages/extension/src/ui/action/App.vue and new restricted/index.vue): Verify restricted state management, modal interactions, recovery phrase flow, and event propagation are correctly isolated from main app
    • Routescan activity handler (packages/extension/src/providers/ethereum/libs/activity-handlers/providers/routescan/index.ts): Validate API request building, transaction normalization logic, error handling for malformed responses, and proper field mappings to Activity objects
    • Changelly RBTC floating-rate flow (packages/swap/src/providers/changelly/index.ts): Confirm method selection logic (getFixRate vs getExchangeAmount), response ID handling, and amount parameter propagation throughout quote/swap paths
    • Network migrations: Verify endpoint changes (wss→https conversions, RPC provider switches) don't break existing functionality; confirm Nibiru testnet configuration is correct
    • Removed network cleanup: Ensure all references to deleted networks (Canto, ZChains, ProofOfPlayApex) are fully removed and won't cause runtime errors across asset handlers, token lists, and dapp configs

Possibly related PRs

Suggested reviewers

  • gamalielhere
  • NickKelly1

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Feat/restricted popup' accurately reflects the main changes: introducing a restricted access UI component and related restriction handling logic for users in geographically restricted regions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Nov 24, 2025

💼 Build Files
chrome: enkrypt-chrome-3c1b1121.zip
firefox: enkrypt-firefox-3c1b1121.zip

💉 Virus total analysis
chrome: 3c1b1121
firefox: 3c1b1121

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (7)
packages/extension/src/libs/utils/providersDetails.ts (2)

1-1: Add missing semicolon for consistency.

-import { ProviderName, ProviderNameProper } from "@enkryptcom/swap/src/types"
+import { ProviderName, ProviderNameProper } from "@enkryptcom/swap/src/types";

11-20: Add type annotation for type safety and IntelliSense.

The exported mapping should be explicitly typed to catch errors if the structure is misused and to improve IDE support.

+import type { ProviderName } from "@enkryptcom/swap/src/types";
+
+interface ProviderDetails {
+  name: string;
+  logo: string;
+}
+
-export default {
+const providersDetails: Record<ProviderName, ProviderDetails> = {
   [ProviderName.changelly]: { name: ProviderNameProper.changelly, logo: changellyLogo },
   [ProviderName.oneInch]: { name: ProviderNameProper.oneInch, logo: oneInch },
   [ProviderName.oneInchFusion]: { name: ProviderNameProper.oneInchFusion, logo: oneInch },
   [ProviderName.paraswap]: { name: ProviderNameProper.paraswap, logo: paraswap },
   [ProviderName.zerox]: { name: ProviderNameProper.zerox, logo: zerox },
   [ProviderName.rango]: { name: ProviderNameProper.rango, logo: rango },
   [ProviderName.jupiter]: { name: ProviderNameProper.jupiter, logo: jupiter },
-  [ProviderName.okx]: { name: ProviderNameProper.okx, logo: okx }
-}
+  [ProviderName.okx]: { name: ProviderNameProper.okx, logo: okx },
+};
+
+export default providersDetails;

This ensures all ProviderName values are present and the structure is correct.

packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/index.vue (2)

3-7: Add defensive check for provider details access.

Direct access to providersDetails[props.pickedTrade.provider] could throw a runtime error if the provider is not in the mapping (e.g., due to future additions to ProviderName without updating providersDetails).

Consider adding a fallback:

-    <h3>
-      Best offer including network fee powered by
-      <img :src="providersDetails[props.pickedTrade.provider].logo" />
-      {{ providersDetails[props.pickedTrade.provider].name }}
-    </h3>
+    <h3>
+      Best offer including network fee powered by
+      <template v-if="providersDetails[props.pickedTrade.provider]">
+        <img :src="providersDetails[props.pickedTrade.provider].logo" />
+        {{ providersDetails[props.pickedTrade.provider].name }}
+      </template>
+      <template v-else>
+        {{ props.pickedTrade.provider }}
+      </template>
+    </h3>

Alternatively, create a computed property that safely retrieves provider details.


48-55: Apply consistent defensive check and prefer CSS for sizing.

Similar to the header, add a defensive check for provider details access. Also, prefer CSS classes over inline height attributes for maintainability.

       <p>
         Provider:
-        <img
-          height="15px"
-          :src="providersDetails[props.pickedTrade.provider].logo"
-        />
-        {{ providersDetails[props.pickedTrade.provider].name }}
+        <template v-if="providersDetails[props.pickedTrade.provider]">
+          <img
+            class="provider-logo"
+            :src="providersDetails[props.pickedTrade.provider].logo"
+          />
+          {{ providersDetails[props.pickedTrade.provider].name }}
+        </template>
+        <template v-else>
+          {{ props.pickedTrade.provider }}
+        </template>
       </p>

Add to styles:

&__info {
  .provider-logo {
    height: 15px;
  }
  // ... existing styles
}
packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-list-item.vue (1)

45-50: Consider making provider required or using null as default.

The default empty string '' is not a valid ProviderName enum value, which could lead to the "Unknown Provider" fallback being shown unexpectedly. Consider making the prop required (since every trade should have a provider) or using null/undefined as the default to make the intent clearer.

Option 1 (Make required):

   provider: {
     type: String as PropType<ProviderName>,
-    default: () => {
-      return '';
-    },
+    required: true,
   },

Option 2 (Use null):

   provider: {
-    type: String as PropType<ProviderName>,
+    type: String as PropType<ProviderName | null>,
     default: () => {
-      return '';
+      return null;
     },
   },

Then update the template check:

         {{
-          props.provider
+          props.provider && providersDetails[props.provider]
             ? providersDetails[props.provider].name
             : 'Unknown Provider'
         }}
packages/extension/src/ui/action/views/restricted/index.vue (1)

65-99: Minor UX/accessibility nits in CTA elements

  • View My Secret Recovery Phrase and Contact support are plain <div>s with @click; consider using <button> (or add keyboard handlers/roles) so keyboard users can activate them.
  • The More info link uses href="#" without a click handler; either wire it to a real URL or prevent default until the destination is ready to avoid odd hash changes.
packages/extension/src/ui/action/App.vue (1)

433-460: Be explicit about sending all addresses to the partner API

checkAddresses currently sends every active and inactive account address to the walletscreen endpoint. That’s likely intended, but it’s a cross‑cutting privacy/compliance decision; just make sure this behavior (including inactive accounts) is explicitly agreed and documented, since it expands the surface of which addresses are disclosed to the partner.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1bd8c09 and d6fe1e5.

⛔ Files ignored due to path filters (7)
  • packages/extension/src/ui/action/assets/swap/0x-logo.png is excluded by !**/*.png
  • packages/extension/src/ui/action/assets/swap/1inch-logo.png is excluded by !**/*.png
  • packages/extension/src/ui/action/assets/swap/changelly-logo.png is excluded by !**/*.png
  • packages/extension/src/ui/action/assets/swap/jupiter-logo.png is excluded by !**/*.png
  • packages/extension/src/ui/action/assets/swap/okx-logo.png is excluded by !**/*.png
  • packages/extension/src/ui/action/assets/swap/paraswap-logo.png is excluded by !**/*.png
  • packages/extension/src/ui/action/assets/swap/rango-logo.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • packages/extension/package.json (1 hunks)
  • packages/extension/src/libs/utils/providersDetails.ts (1 hunks)
  • packages/extension/src/ui/action/App.vue (6 hunks)
  • packages/extension/src/ui/action/views/restricted/index.vue (1 hunks)
  • packages/extension/src/ui/action/views/settings/components/settings-inner-header.vue (2 hunks)
  • packages/extension/src/ui/action/views/settings/views/settings-recovery/index.vue (2 hunks)
  • packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-list-item.vue (3 hunks)
  • packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-list.vue (1 hunks)
  • packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/index.vue (4 hunks)
  • packages/swap/src/types/index.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: buildAll
🔇 Additional comments (8)
packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-list-item.vue (1)

4-16: Good defensive coding with fallback!

The conditional checks for providersDetails[props.provider] and the "Unknown Provider" fallback ensure the component won't crash if an unmapped provider is passed.

packages/extension/package.json (1)

7-7: ****

The review comment assumes that prebuild steps were removed from the build workflow. However, analysis of the codebase reveals:

  • No prebuild or kadena:prebuild script is defined anywhere in packages/extension/package.json
  • Zero references to "prebuild" exist in the entire codebase
  • The Vite build pipeline is fully configured and functional
  • The get-system-info.js script is already properly integrated into the build:firefox script

The changes shown do not involve removal of any prebuild steps—this workflow was already Vite-based. There are no broken dependencies or missing build setup to address.

Likely an incorrect or invalid review comment.

packages/extension/src/ui/action/views/swap/views/swap-best-offer/components/swap-best-offer-block/components/best-offer-list.vue (1)

8-8: Type compatibility verified—the change is correct and ready to merge.

The :provider="trade.provider" binding correctly passes the swap provider information from ProviderSwapResponse to BestOfferListItem. Both the source (trade.provider: ProviderName) and target prop (provider: PropType<ProviderName>) use the same ProviderName enum from @enkryptcom/swap, ensuring full type safety. The provider values are properly consumed by the providersDetails mapping for UI rendering.

packages/extension/src/ui/action/views/settings/components/settings-inner-header.vue (1)

3-3: Optional back button via hasBack prop looks good

Conditionally rendering the back button with hasBack (defaulting to true) keeps existing behavior intact while allowing consumers like the restricted flow to hide it when needed. No functional issues spotted.

Also applies to: 27-30

packages/extension/src/ui/action/views/settings/views/settings-recovery/index.vue (1)

3-7: Event/prop forwarding into SettingsInnerHeader is wired correctly

Forwarding $attrs and explicitly passing hasBack lets parents (like the restricted view) handle window:back/window:close through the header while keeping the default behavior unchanged. Looks consistent with the header’s API.

Also applies to: 49-53

packages/extension/src/ui/action/views/restricted/index.vue (1)

1-55: Restricted recovery flow wiring looks correct

The unlock → displayMnemonic → overlay flow is coherent: the sign modal closes before showing the mnemonic, the overlay click and header events all funnel to closeMnemonic, and the mnemonic state is cleared on close. This gives a clean one-way path without leaving sensitive data around in component state longer than needed.

packages/extension/src/ui/action/App.vue (2)

2-7: Restricted container integration is clean

Conditionally swapping the main app shell for <restricted /> based on foundRestrictedAddress and overriding .app sizing with .restricted-container is straightforward and shouldn’t regress existing layout; existing flows continue under the v-else branch.

Also applies to: 616-619


121-121: New Restricted import matches template usage

The import path for Restricted aligns with the new <restricted /> usage in the template and keeps the component local to the popup UI. Nothing concerning here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
packages/extension/src/ui/action/App.vue (1)

318-331: Harden checkAddresses against network/JSON failures and avoid unhandled rejections

checkAddresses does one fetch per account and is invoked from setNetwork without await. Because the body uses raw fetch and addressFetch.json() with no try/catch or res.ok check, any network error, invalid JSON, or unexpected status will reject the promise and surface as an unhandled rejection while silently skipping the remaining checks. This is essentially the same issue raised in the previous review and still worth addressing.

Consider making checkAddresses best-effort and self-contained, e.g.:

  • Short-circuit if foundRestrictedAddress.value is already true.
  • Skip accounts without an address and dedupe addresses to avoid redundant calls.
  • Wrap each request in try/catch, treat non‑OK responses as failures, and stop on the first confirmed restricted address.
  • Optionally log failures so you can diagnose partner‑API issues.

Example patch:

-const foundRestrictedAddress = ref(false);
-
-const checkAddresses = async (
-  activeAccounts: AccountsHeaderData['activeAccounts'],
-  inactiveAccounts: AccountsHeaderData['inactiveAccounts'],
-) => {
-  const accountsArray = [...activeAccounts, ...inactiveAccounts];
-  for (const account of accountsArray) {
-    if (foundRestrictedAddress.value) {
-      break;
-    }
-
-    const addressFetch = await fetch(
-      `https://partners.mewapi.io/o/walletscreen?address=${account.address}`,
-    );
-    const { isRestricted } = await addressFetch.json();
-    foundRestrictedAddress.value = isRestricted;
-  }
-};
+const foundRestrictedAddress = ref(false);
+
+const checkAddresses = async (
+  activeAccounts: AccountsHeaderData['activeAccounts'],
+  inactiveAccounts: AccountsHeaderData['inactiveAccounts'],
+) => {
+  if (foundRestrictedAddress.value) return;
+
+  const addresses = [...activeAccounts, ...inactiveAccounts]
+    .map(acc => acc.address)
+    .filter((addr): addr is string => !!addr);
+
+  for (const address of new Set(addresses)) {
+    if (foundRestrictedAddress.value) break;
+
+    try {
+      const res = await fetch(
+        `https://partners.mewapi.io/o/walletscreen?address=${address}`,
+      );
+      if (!res.ok) continue;
+      const { isRestricted } = await res.json();
+      if (isRestricted) {
+        foundRestrictedAddress.value = true;
+        break;
+      }
+    } catch (err) {
+      console.error(
+        'Failed to check restricted status for address',
+        address,
+        err,
+      );
+      // Decide whether to continue or abort based on product requirements
+      break;
+    }
+  }
+};

If you want to keep the checks completely fire‑and‑forget, you can additionally make the call explicit about that intent:

// inside setNetwork
void checkAddresses(activeAccounts, inactiveAccounts).catch(err =>
  console.error('checkAddresses failed', err),
);

Also applies to: 432-450

🧹 Nitpick comments (2)
packages/extension/src/ui/action/App.vue (2)

2-7: Confirm restricted-view lifecycle and new root wrapper behavior

Top-level v-if="foundRestrictedAddress" correctly gives the restricted view precedence over loading and main app content. Note that in this file foundRestrictedAddress is only ever set (to true) and never cleared, so once a restricted address is detected this App instance will remain locked in the restricted view for its lifetime. If the recovery flow is meant to let users resume normal usage in the same session, you’ll need an event/prop from <restricted /> to clear that flag, or a different navigation strategy.

Also, the extra root <div> now wraps .app; if any CSS/tests/scripts assumed .app was the root element, they may need updating.

Also applies to: 13-22


458-486: Consider re-checking restrictions on address change if the rule is per-address

Right now restricted checks only run from setNetwork / subnet changes. If a user adds or selects a different account within the same network (via onSelectedAddressChanged), checkAddresses is not called again, so a newly added restricted address might not be detected until the next network change.

If restrictions are meant to apply per-active address rather than just “any address ever seen on this network”, consider either:

  • Calling checkAddresses (or a narrower checkAddress(newAccount) helper) from onSelectedAddressChanged, or
  • Moving the logic into a place that runs whenever the accounts list changes.

If the product requirement is strictly “block if any account associated with the wallet is restricted, regardless of selection”, the current setup is fine.

Also applies to: 432-450

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d6fe1e5 and c729efe.

📒 Files selected for processing (1)
  • packages/extension/src/ui/action/App.vue (6 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: buildAll
  • GitHub Check: test
  • GitHub Check: test
🔇 Additional comments (1)
packages/extension/src/ui/action/App.vue (1)

121-121: Restricted component wiring and sizing look consistent

The Restricted import and usage in the template are consistent, and the .restricted-container class applied alongside .app ensures the restricted view can occupy the full popup viewport (100vh/100vw) instead of the fixed 600px height used elsewhere. This matches the intent of a full-screen “access restricted” page.

Also applies to: 606-609

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
packages/extension/src/ui/action/App.vue (2)

342-342: Fire-and-forget call can produce unhandled rejections.

checkAddresses is called without await or .catch(), so any errors will be unobserved. This was flagged in a previous review and remains unresolved.

Either await the call or add explicit error handling:

-  checkAddresses(activeAccounts, inactiveAccounts);
+  checkAddresses(activeAccounts, inactiveAccounts).catch(err => {
+    console.error('Failed to check address restrictions:', err);
+  });

446-462: Add error handling, response validation, and address deduplication.

The implementation still lacks the safeguards recommended in the previous review:

  1. No try-catch around fetch/json() calls → unhandled rejections on network/parse errors
  2. No response.ok check → non-200 responses will fail during JSON parsing
  3. No address deduplication → same address may be checked multiple times

Apply the following improvements:

 const checkAddresses = async (
   activeAccounts: AccountsHeaderData['activeAccounts'],
   inactiveAccounts: AccountsHeaderData['inactiveAccounts'],
 ) => {
+  if (foundRestrictedAddress.value) return;
+
-  const accountsArray = [...activeAccounts, ...inactiveAccounts];
+  const addresses = Array.from(
+    new Set(
+      [...activeAccounts, ...inactiveAccounts]
+        .map(acc => acc.address)
+        .filter(Boolean)
+    )
+  );
+
-  for (const account of accountsArray) {
+  for (const address of addresses) {
     if (foundRestrictedAddress.value) {
       break;
     }

+    try {
-      const addressFetch = await fetch(
-        `https://partners.mewapi.io/o/walletscreen?address=${account.address}`,
-      );
-      const { isRestricted } = await addressFetch.json();
-      foundRestrictedAddress.value = isRestricted;
+      const res = await fetch(
+        `https://partners.mewapi.io/o/walletscreen?address=${address}`,
+      );
+      if (!res.ok) {
+        console.error('Restriction check failed for address', address, res.status);
+        continue;
+      }
+      const { isRestricted } = await res.json();
+      if (isRestricted) {
+        foundRestrictedAddress.value = true;
+        break;
+      }
+    } catch (err) {
+      console.error('Failed to check restricted status for address', address, err);
+      break;
+    }
   }
 };
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c729efe and ca8ebfd.

📒 Files selected for processing (1)
  • packages/extension/src/ui/action/App.vue (8 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: buildAll
  • GitHub Check: test
  • GitHub Check: test
🔇 Additional comments (4)
packages/extension/src/ui/action/App.vue (4)

2-9: LGTM!

The conditional rendering logic correctly prioritizes the restricted view when either geo-based or address-based restrictions are detected.


124-124: LGTM!

The import statement is correctly structured.


165-165: LGTM!

The state declaration is appropriate.


618-621: LGTM!

The fullscreen styling is appropriate for a blocking restricted state.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
packages/extension/src/ui/action/views/restricted/index.vue (3)

50-60: Consider adding keyboard escape handler for better UX.

The mnemonic overlay can be closed by clicking the backdrop but lacks an Escape key handler. Adding @keydown.esc support improves accessibility and matches common modal patterns.

-  <div class="settings__container" v-if="showMnemonic">
+  <div class="settings__container" v-if="showMnemonic" @keydown.esc="closeMnemonic">
     <div class="settings__overlay" @click="closeMnemonic()" />

13-14: Extract hardcoded email to a constant.

The support email address appears in multiple locations (template and script), creating a maintenance burden if it needs to change.

+const SUPPORT_EMAIL = 'support@myetherwallet.com';
+
 const supportAction = () => {
-  window.open('mailto:support@myetherwallet.com', '_blank', 'noopener');
+  window.location.href = `mailto:${SUPPORT_EMAIL}`;
 };

Then update the template:

       If this address has been incorrectly flagged, you can contact us at
-      <a class="blocked-page__support" href="mailto:support@myetherwallet.com"
-        >support@myetherwallet.com</a
+      <a class="blocked-page__support" :href="`mailto:${SUPPORT_EMAIL}`"
+        >{{ SUPPORT_EMAIL }}</a
       >.

Also applies to: 71-73


93-97: Consider validating mnemonic before display.

The displayMnemonic function doesn't validate that the received mnemonic is non-empty. If the parent component passes an empty phrase, the overlay will display with blank content.

 const displayMnemonic = (phrase: MnemonicWithExtraWord) => {
+  if (!phrase.mnemonic) {
+    console.error('Attempted to display empty mnemonic');
+    return;
+  }
   closeUnlock();
   mnemonic.value = phrase;
   showMnemonic.value = true;
 };
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ca8ebfd and deb7190.

📒 Files selected for processing (1)
  • packages/extension/src/ui/action/views/restricted/index.vue (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: buildAll
  • GitHub Check: test
  • GitHub Check: test

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (5)
packages/extension/src/ui/action/views/restricted/index.vue (5)

17-17: Fix or remove the placeholder link.

The "More info" link uses href="#" which causes page jumps and doesn't navigate anywhere. Either provide a valid documentation URL or remove the link until the destination is determined.


20-22: Add keyboard accessibility to the interactive header.

The clickable div lacks keyboard navigation support. Users cannot focus or activate it via keyboard, which violates WCAG accessibility standards.


31-31: Add keyboard accessibility to the support link.

The clickable div lacks keyboard navigation support (tabindex, role, @keydown.enter), preventing keyboard-only users from accessing support.


71-73: Simplify mailto link handling.

Using window.open with '_blank' for a mailto link may not work reliably across all platforms. Mailto links typically don't open in new tabs.


116-130: Remove duplicate height property.

The &__wrap selector has two height declarations: height: auto; at line 124 and height: 568px; at line 127. The second overrides the first, making line 124 redundant.

🧹 Nitpick comments (1)
packages/extension/src/ui/action/views/restricted/index.vue (1)

93-97: Consider validating the mnemonic phrase parameter.

The displayMnemonic function stores and displays the phrase without checking if it contains valid data. If an empty or malformed phrase is passed, users might see a blank recovery screen.

Consider adding a guard:

 const displayMnemonic = (phrase: MnemonicWithExtraWord) => {
+  if (!phrase?.mnemonic) {
+    console.error('Invalid mnemonic phrase received');
+    return;
+  }
   closeUnlock();
   mnemonic.value = phrase;
   showMnemonic.value = true;
 };
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between deb7190 and 45936d7.

📒 Files selected for processing (1)
  • packages/extension/src/ui/action/views/restricted/index.vue (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: buildAll
  • GitHub Check: test
  • GitHub Check: test
🔇 Additional comments (2)
packages/extension/src/ui/action/views/restricted/index.vue (2)

88-91: Good practice: Sensitive data is properly cleared.

The closeMnemonic function correctly clears the mnemonic data when the overlay is closed, which is important for security when handling recovery phrases.


165-274: Styles are well-organized.

The blocked-page styles are clearly structured with appropriate selectors, consistent spacing, and readable formatting. The visual hierarchy and layout rules are well-defined.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
packages/extension/src/ui/action/views/restricted/index.vue (4)

24-26: Add keyboard accessibility to interactive elements.

The clickable div lacks keyboard accessibility—users cannot navigate to or activate it via keyboard. This was flagged in a previous review and remains unaddressed.


35-35: Add keyboard accessibility to the support link.

The clickable div for "Contact support" lacks keyboard accessibility. This was flagged in a previous review and remains unaddressed.


75-77: Simplify mailto link handling.

Using window.open with '_blank' for a mailto link is unusual and was flagged in a previous review. This remains unaddressed.


128-131: Remove duplicate height property.

The &__wrap selector has two height declarations: height: auto; (line 128) and height: 568px; (line 131). This was flagged in a previous review and remains unaddressed.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 45936d7 and 475bb3e.

📒 Files selected for processing (1)
  • packages/extension/src/ui/action/views/restricted/index.vue (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: buildAll
  • GitHub Check: test
  • GitHub Check: test
🔇 Additional comments (1)
packages/extension/src/ui/action/views/restricted/index.vue (1)

92-95: Good security practice: clearing sensitive data.

The closeMnemonic function properly resets the mnemonic to empty values when the overlay is closed, which is a good security practice to minimize exposure of sensitive data in memory.

@kvhnuke kvhnuke changed the base branch from develop to feat/provider-names November 25, 2025 23:43
- Enhanced formatting and indentation in `eth-verify-transaction.vue` for better code clarity.
- Streamlined the structure of `App.vue` by reducing unnecessary divs and improving component usage.
- Updated `lock-screen/index.vue` to improve layout and readability.
- Refined `restricted/index.vue` to enhance the user experience with clearer conditional rendering.
- Improved `swap/index.vue` by organizing component props and events for better readability.
- Enhanced `best-offer-list-item.vue` and `index.vue` for better structure and clarity.
- Added geo-restriction checks in `onboard/App.vue` to improve user flow.
- Standardized code style in `base58.ts`, `cross-browser.ts`, and various interface files for consistency.
- Ensured all interface methods end with a semicolon for uniformity.
@kvhnuke kvhnuke merged commit 6fa4721 into feat/provider-names Nov 27, 2025
5 checks passed
@kvhnuke kvhnuke deleted the feat/restricted-popup branch November 27, 2025 00:05
@coderabbitai coderabbitai bot mentioned this pull request Nov 27, 2025
This was referenced Dec 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants