diff --git a/ui/hooks/useMultichainAccountsIntroModal.test.ts b/ui/hooks/useMultichainAccountsIntroModal.test.ts index a2faf6c2577..a84a613d402 100644 --- a/ui/hooks/useMultichainAccountsIntroModal.test.ts +++ b/ui/hooks/useMultichainAccountsIntroModal.test.ts @@ -1,4 +1,4 @@ -import { lt as semverLt } from 'semver'; +import { lt as semverLt, coerce as semverCoerce } from 'semver'; // Test the core logic independently of React hooks describe('BIP-44 Banner Logic', () => { @@ -16,7 +16,17 @@ describe('BIP-44 Banner Logic', () => { const isUpgradeFromLowerThanBip44Version = Boolean( lastUpdatedFromVersion && typeof lastUpdatedFromVersion === 'string' && - semverLt(lastUpdatedFromVersion, BIP44_ACCOUNTS_INTRODUCTION_VERSION), + (() => { + try { + const coercedVersion = semverCoerce(lastUpdatedFromVersion); + return ( + coercedVersion && + semverLt(coercedVersion, BIP44_ACCOUNTS_INTRODUCTION_VERSION) + ); + } catch { + return false; + } + })(), ); return ( @@ -171,5 +181,32 @@ describe('BIP-44 Banner Logic', () => { ); expect(result).toBe(false); }); + + it('handles invalid semver version like 13.9.0.150 (4-part version)', () => { + // This tests the bug fix for extensions with non-standard version formats + const result = shouldShowBip44Banner( + true, + true, + false, + Date.now(), + '13.9.0.150', // Invalid semver - 4 parts + true, + ); + // Should gracefully handle and return false (coerced to 13.9.0 which is >= 13.5.0) + expect(result).toBe(false); + }); + + it('handles invalid semver for older version like 13.4.0.100', () => { + const result = shouldShowBip44Banner( + true, + true, + false, + Date.now(), + '13.4.0.100', // Invalid semver - 4 parts, but coerces to 13.4.0 + true, + ); + // Should coerce to 13.4.0 and show banner + expect(result).toBe(true); + }); }); }); diff --git a/ui/hooks/useMultichainAccountsIntroModal.ts b/ui/hooks/useMultichainAccountsIntroModal.ts index 0d37eb8b4c6..20ab848cbe4 100644 --- a/ui/hooks/useMultichainAccountsIntroModal.ts +++ b/ui/hooks/useMultichainAccountsIntroModal.ts @@ -1,5 +1,5 @@ import { useState, useEffect } from 'react'; -import { lt as semverLt } from 'semver'; +import { lt as semverLt, coerce as semverCoerce } from 'semver'; import { useAppSelector } from '../store/store'; import { getIsMultichainAccountsState2Enabled } from '../selectors/multichain-accounts/feature-flags'; import { getLastUpdatedFromVersion } from '../selectors/selectors'; @@ -40,10 +40,22 @@ export function useMultichainAccountsIntroModal( const isMainWalletArea = location.pathname === DEFAULT_ROUTE; // Check if this is an upgrade from a version lower than BIP-44 introduction version + // Extension versions may not be valid semver therefore we coerce them first const isUpgradeFromLowerThanBip44Version = Boolean( lastUpdatedFromVersion && typeof lastUpdatedFromVersion === 'string' && - semverLt(lastUpdatedFromVersion, BIP44_ACCOUNTS_INTRODUCTION_VERSION), + (() => { + try { + const coercedVersion = semverCoerce(lastUpdatedFromVersion); + return ( + coercedVersion && + semverLt(coercedVersion, BIP44_ACCOUNTS_INTRODUCTION_VERSION) + ); + } catch { + // If version can't be parsed, assume it's not from an old version + return false; + } + })(), ); // Show modal only for upgrades from versions < BIP-44 introduction version