Skip to content

Drop-down menu#190

Merged
kumavis merged 5 commits intoeyeballsfrom
MenuDroppo
May 19, 2016
Merged

Drop-down menu#190
kumavis merged 5 commits intoeyeballsfrom
MenuDroppo

Conversation

@danfinlay
Copy link
Copy Markdown
Contributor

Got a nicely animating drop-down menu with animated sandwich icon implemented for our UX overhaul branch.

Merge at your pleasure @kumavis

ui/app/app.js Outdated
src: '/images/icon-128.png',
}),

// metamask namlterChangese
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

typo

@kumavis kumavis merged commit fbc7a48 into eyeballs May 19, 2016
@kumavis kumavis deleted the MenuDroppo branch May 20, 2016 23:54
SeungjunWe pushed a commit to DcentWallet/metamask-extension that referenced this pull request Jul 13, 2020
yqrashawn added a commit to yqrashawn/conflux-portal that referenced this pull request Aug 31, 2020
github-merge-queue bot pushed a commit that referenced this pull request Jan 29, 2026
Do not merge before this gets in
MetaMask/core#7413

## **Description**
# Performance Comparison: Per-Chain Token Cache Storage

This PR implements per-chain file storage for `tokensChainsCache` in
`TokenListController`, replacing the single-file approach. Each chain's
token list is now stored in a separate file via StorageService, reducing
write amplification during incremental updates.

---

## 📊 Summary

| Category | This PR | Main Branch | Improvement |
|----------|---------|-------------|-------------|
| Cold restart (getAllPersistedState) | **216.20ms** | **374.30ms** |
**42% faster** |
| Cold restart (cache load) | **~310ms** (parallel) | Included in state
| ----- |
| Onboarding - Token cache | **4.40MB** (StorageService) | **4.40MB**
(in state) | Stored separately |
| Onboarding - Background saves | **~23MB** each | **~28MB** each |
**~5MB less per save** |
| Onboarding - Token cache in saves | ❌ No | ✅ Yes | **Eliminated** |
| **Add Monad** | **39KB** (new chain only) | **~4.4MB** (full cache
rewritten) | **Only new chain** |
| **Add Avalanche** | **157KB** (new chain only) | **~4.6MB** (full
cache rewritten) | **Only new chain** |
| **Background saves (idle)** | **~23MB** | **~28MB** | **~18% smaller**
|
| **TokenListController in state** | **0.04KB** | **4,601KB** | **Cache
moved out** |

**Key Results**:
1. **Adding a single chain on main branch** triggers a state save that
rewrites all TokenListController cache (~4.6MB) plus all other
controllers (~23MB) = ~28MB total.
2. **This PR writes ONLY the new chain** (e.g., 39KB for Monad) to
StorageService. The full token cache is NOT rewritten.
3. **Background saves are ~5MB smaller** (~23MB vs ~28MB) because the
token cache is stored separately.

---

## 🧪 Test Scenarios

### Scenario 1: Cold Restart (Existing User)

**Setup**: Extension with 10 networks cached (8 popular + Monad +
Avalanche), then browser restart.

#### This PR

**Controller Storage:**
```
[ControllerStorage PERF] getAllPersistedState complete - 216.20ms
```

**StorageService - getAllKeys:**
```
[StorageService PERF] getAllKeys TokenListController - 10 keys found - 277.60ms
```

**StorageService - Per-chain getItem (parallel reads):**
| Chain | Size | Read Time |
|-------|------|-----------|
| 0x1 (Ethereum) | 2022.39KB | 80.40ms |
| 0x38 (BSC) | 1045.19KB | 125.90ms |
| 0x2105 (Base) | 436.73KB | 97.20ms |
| 0x89 (Polygon) | 388.91KB | 128.30ms |
| 0xa4b1 (Arbitrum) | 345.79KB | 159.50ms |
| 0xa86a (Avalanche) | 156.90KB | 161.60ms |
| 0xa (Optimism) | 125.76KB | 132.20ms |
| 0xe708 (Linea) | 40.13KB | 163.20ms |
| 0x8f (Monad) | 39.15KB | 131.80ms |
| 0xaa36a7 (Sepolia) | 0.04KB | 162.70ms |

**Total cache size: ~4.60MB across 10 chains**

#### Main Branch

**Cold restart with 10 networks cached (8 popular + Monad +
Avalanche):**
```
[ControllerStorage PERF] getAllPersistedState started
[ControllerStorage PERF] getAllPersistedState complete - 374.30ms
[ControllerStorage PERF] TokenListController read - 4601.13KB - 374.30ms
```

#### Comparison

| Metric | This PR | Main Branch | Improvement |
|--------|---------|-------------|-------------|
| **getAllPersistedState** | **216.20ms** | **374.30ms** | **42%
faster** |
| TokenListController in state | **0.04KB** | **4,601KB** | Moved to
StorageService |
| StorageService cache load | **~163ms** (10 chains parallel) | N/A |
Separate loading |
| Total chains | 10 | 10 | Same |
| Total state size | ~23MB | ~28MB | **~18% smaller** |

**Key insight**: The main state loads **158ms faster** on this PR
because it's ~5MB smaller. The token cache is loaded separately via
StorageService in parallel during controller initialization.

---

### Scenario 2: Fresh Onboarding

**Setup**: Fresh wallet creation, enable all popular networks, wait for
token lists to fetch.

#### This PR

**Initial state (fresh install):**
```
[ControllerStorage PERF] getAllPersistedState complete - 13.70ms
[StorageService PERF] getAllKeys TokenListController - 0 keys found - 23.50ms
```

**Per-chain writes as networks are enabled:**
| Chain | Size | Stringify | Write | Total |
|-------|------|-----------|-------|-------|
| 0xaa36a7 (Sepolia) | 0.04KB | 0.00ms | 12.00ms | 12.00ms |
| 0xe708 (Linea) | 40.13KB | 0.00ms | 81.70ms | 81.70ms |
| 0xa (Optimism) | 125.76KB | 0.20ms | 81.20ms | 81.40ms |
| 0x2105 (Base) | 436.73KB | 0.80ms | 79.10ms | 79.90ms |
| 0x89 (Polygon) | 388.91KB | 0.80ms | 72.80ms | 73.60ms |
| 0xa4b1 (Arbitrum) | 345.79KB | 0.80ms | 67.10ms | 67.90ms |
| 0x1 (Ethereum) | 2022.39KB | 4.20ms | 68.40ms | 72.60ms |
| 0x38 (BSC) | 1045.19KB | 1.90ms | 37.80ms | 39.70ms |

**Summary:**
- **Total data written**: ~4.40MB (8 individual writes)
- **Number of writes**: 8 (one per chain)
- **Total write time**: ~509ms (sum of individual writes)

#### Main Branch

**Initial state (fresh install):**
```
[ControllerStorage PERF] getAllPersistedState complete - 14.60ms
[ControllerStorage PERF] set() - TokenListController size: 0.06KB
[ControllerStorage PERF] set() complete - 9952.04KB - 129.10ms
```

**After clicking "All Popular Networks":**
```
[ControllerStorage PERF] set() - TokenListController size: 4405.07KB
[ControllerStorage PERF] set() complete - 27830.24KB - 526.70ms
```

**Summary:**
- **TokenListController size**: 4,405KB (~4.4MB) - cached in controller
state
- **Total state written**: 27,830KB (~27.2MB) - entire MetaMask state
- **Write time**: 526.70ms

#### Comparison

| Metric | This PR | Main Branch | Difference |
|--------|---------|-------------|------------|
| Token cache data | **4.40MB** | **4.40MB** | Same amount |
| Token cache location | **StorageService** (separate) | **Main state**
| Separated |
| Background save size | **~23MB** | **~28MB** | **~5MB smaller** |
| Token cache in every save | ❌ **No** | ✅ **Yes** | **Eliminated** |

**Key insight**: Both branches have continuous background saves. On main
branch, every save includes the ~4.4MB token cache. On this PR, the
token cache is stored separately via StorageService, making each
background save ~5MB smaller.

---

### Scenario 3: Add New Chain

**Setup**: Existing wallet with cached networks, add a new network.

#### This PR

**Avalanche (0xa86a)**:
```
[StorageService PERF] setItem TokenListController:tokensChainsCache:0xa86a - 156.90KB - stringify: 0.80ms, write: 137.20ms, total: 138.00ms
```

**Monad (0x8f)**:
```
[StorageService PERF] setItem TokenListController:tokensChainsCache:0x8f - 39.15KB - stringify: 0.00ms, write: 2.40ms, total: 2.40ms
```

**zkSync Era (0x144)**:
```
[StorageService PERF] setItem TokenListController:tokensChainsCache:0x144 - 12.98KB - stringify: 0.00ms, write: 0.90ms, total: 0.90ms
```

**Polygon (0x89)**:
```
[StorageService PERF] setItem TokenListController:tokensChainsCache:0x89 - 388.91KB - stringify: 0.90ms, write: 15.40ms, total: 16.30ms
```

#### Main Branch

**Adding Monad (0x8f) to existing cache:**
```
[ControllerStorage PERF] set() - TokenListController size: 4444.22KB
[ControllerStorage PERF] set() complete - 27877.62KB - 569.00ms
```

**Adding Avalanche (0xa86a) to existing cache:**
```
[ControllerStorage PERF] set() - TokenListController size: 4601.13KB
[ControllerStorage PERF] set() complete - 28036.55KB - 559.30ms
```

**Note**: Each chain addition triggers a full state save that includes
ALL TokenListController cache (~4.6MB) plus ALL other controllers
(~23MB) = ~28MB total.

#### Comparison

**Token cache write for new chain:**
| Chain | This PR | Main Branch | Difference |
|-------|---------|-------------|------------|
| **Monad (39KB)** | 39KB to StorageService | Full ~4.4MB cache
rewritten | **Only new chain written** |
| **Avalanche (157KB)** | 157KB to StorageService | Full ~4.6MB cache
rewritten | **Only new chain written** |

**Total state save triggered:**
| Metric | This PR | Main Branch | Difference |
|--------|---------|-------------|------------|
| State size | ~23MB (no cache) | ~28MB (with cache) | **~5MB smaller**
|
| Token cache included | ❌ No | ✅ Yes | **Separated** |
| New chain write | **39-157KB** (separate file) | Included in 28MB |
**Isolated** |

---

## 📋 Raw Logs

### This PR - Cold Restart
```
[ControllerStorage PERF] getAllPersistedState started
[ControllerStorage PERF] getAllPersistedState complete - 216.20ms
[StorageService PERF] getAllKeys TokenListController - 10 keys found - 277.60ms
[StorageService PERF] getItem TokenListController:tokensChainsCache:0x1 - 2022.39KB - read: 80.40ms, total: 80.40ms
[StorageService PERF] getItem TokenListController:tokensChainsCache:0x2105 - 436.73KB - read: 97.20ms, total: 97.20ms
[StorageService PERF] getItem TokenListController:tokensChainsCache:0x38 - 1045.19KB - read: 125.80ms, total: 125.90ms
[StorageService PERF] getItem TokenListController:tokensChainsCache:0x89 - 388.91KB - read: 128.30ms, total: 128.30ms
[StorageService PERF] getItem TokenListController:tokensChainsCache:0x8f - 39.15KB - read: 131.80ms, total: 131.80ms
[StorageService PERF] getItem TokenListController:tokensChainsCache:0xa - 125.76KB - read: 132.20ms, total: 132.20ms
[StorageService PERF] getItem TokenListController:tokensChainsCache:0xa4b1 - 345.79KB - read: 159.50ms, total: 159.50ms
[StorageService PERF] getItem TokenListController:tokensChainsCache:0xa86a - 156.90KB - read: 161.60ms, total: 161.60ms
[StorageService PERF] getItem TokenListController:tokensChainsCache:0xaa36a7 - 0.04KB - read: 162.70ms, total: 162.70ms
[StorageService PERF] getItem TokenListController:tokensChainsCache:0xe708 - 40.13KB - read: 163.20ms, total: 163.20ms
```

### This PR - Onboarding
```
[ControllerStorage PERF] getAllPersistedState started
[ControllerStorage PERF] getAllPersistedState complete - 13.70ms
[StorageService PERF] getAllKeys TokenListController - 0 keys found - 23.50ms
[StorageService PERF] setItem TokenListController:tokensChainsCache:0xaa36a7 - 0.04KB - stringify: 0.00ms, write: 12.00ms, total: 12.00ms
[StorageService PERF] setItem TokenListController:tokensChainsCache:0xe708 - 40.13KB - stringify: 0.00ms, write: 81.70ms, total: 81.70ms
[StorageService PERF] setItem TokenListController:tokensChainsCache:0xa - 125.76KB - stringify: 0.20ms, write: 81.20ms, total: 81.40ms
[StorageService PERF] setItem TokenListController:tokensChainsCache:0x2105 - 436.73KB - stringify: 0.80ms, write: 79.10ms, total: 79.90ms
[StorageService PERF] setItem TokenListController:tokensChainsCache:0x89 - 388.91KB - stringify: 0.80ms, write: 72.80ms, total: 73.60ms
[StorageService PERF] setItem TokenListController:tokensChainsCache:0xa4b1 - 345.79KB - stringify: 0.80ms, write: 67.10ms, total: 67.90ms
[StorageService PERF] setItem TokenListController:tokensChainsCache:0x1 - 2022.39KB - stringify: 4.20ms, write: 68.40ms, total: 72.60ms
[StorageService PERF] setItem TokenListController:tokensChainsCache:0x38 - 1045.19KB - stringify: 1.90ms, write: 37.80ms, total: 39.70ms
```

### This PR - Add New Chain
```
# Adding Monad (39KB)
[StorageService PERF] setItem TokenListController:tokensChainsCache:0x8f - 39.15KB - stringify: 0.10ms, write: 1.60ms, total: 1.70ms
[ControllerStorage PERF] set() - TokenListController size: 0.04KB
[ControllerStorage PERF] set() complete - 23433.75KB - 418.90ms

# Adding Avalanche (157KB)
[StorageService PERF] setItem TokenListController:tokensChainsCache:0xa86a - 156.90KB - stringify: 0.50ms, write: 5.30ms, total: 5.80ms
[ControllerStorage PERF] set() - TokenListController size: 0.04KB
[ControllerStorage PERF] set() complete - 23435.80KB - 416.10ms
```

### Main Branch - Cold Restart
```
[ControllerStorage PERF] getAllPersistedState started
[ControllerStorage PERF] getAllPersistedState complete - 374.30ms
[ControllerStorage PERF] TokenListController read - 4601.13KB - 374.30ms
[ControllerStorage PERF] set() - TokenListController size: 4601.13KB
[ControllerStorage PERF] set() complete - 28033.23KB - 426.60ms
[ControllerStorage PERF] set() - TokenListController size: 4601.13KB
[ControllerStorage PERF] set() complete - 28033.01KB - 564.00ms
```

### Main Branch - Onboarding
```
[ControllerStorage PERF] getAllPersistedState started
[ControllerStorage PERF] getAllPersistedState complete - 14.60ms
[ControllerStorage PERF] set() complete - 0.06KB - 0.30ms
[ControllerStorage PERF] set() - TokenListController size: 0.06KB
[ControllerStorage PERF] set() complete - 9952.04KB - 129.10ms
[ControllerStorage PERF] set() - TokenListController size: 0.06KB
[ControllerStorage PERF] set() complete - 9952.30KB - 130.20ms
[ControllerStorage PERF] set() - TokenListController size: 0.06KB
[ControllerStorage PERF] set() complete - 9952.67KB - 136.10ms
[ControllerStorage PERF] set() - TokenListController size: 0.06KB
[ControllerStorage PERF] set() complete - 9952.97KB - 136.50ms
[ControllerStorage PERF] set() - TokenListController size: 0.06KB
[ControllerStorage PERF] set() complete - 9955.72KB - 142.20ms
[ControllerStorage PERF] set() - TokenListController size: 4405.07KB
[ControllerStorage PERF] set() complete - 27830.24KB - 526.70ms
```

### Main Branch - Add New Chain (Monad + Avalanche)
```
# Adding Monad (39KB)
[ControllerStorage PERF] set() - TokenListController size: 4444.22KB
[ControllerStorage PERF] set() complete - 27877.62KB - 569.00ms

# Adding Avalanche (157KB)
[ControllerStorage PERF] set() - TokenListController size: 4601.13KB
[ControllerStorage PERF] set() complete - 28036.55KB - 559.30ms
```

---

## 🔧 How Performance Was Measured

Performance logging was added to:

1. **BrowserStorageAdapter**
(`app/scripts/lib/stores/browser-storage-adapter.ts`)
   - Logs for `getItem`, `setItem`, `getAllKeys` operations
   - Measures read time, stringify time, write time, and data size

2. **ExtensionStore** (`app/scripts/lib/stores/extension-store.ts`)
   - Logs for `getAllPersistedState` and controller state writes
   - Measures TokenListController-specific read/write performance

To enable logging, set `PERF_LOGGING_ENABLED = true` in both files.

---

## 📝 Logging Code Reference (Main Branch)

The following code was added to `extension-store.ts` on main branch to
capture performance metrics:

### Helper Functions (add at top of file after imports)

```typescript
// ============ PERF LOGGING (for testing) ============
const PERF_LOGGING_ENABLED = true;

function getSizeKB(obj: unknown): string {
  try {
    const str = JSON.stringify(obj);
    return (str.length / 1024).toFixed(2);
  } catch {
    return 'N/A';
  }
}

function logControllerReadPerf(
  controllerName: string,
  data: unknown,
  timeMs: number,
): void {
  if (!PERF_LOGGING_ENABLED) {
    return;
  }
  const sizeKB = getSizeKB(data);
  console.warn(
    `[ControllerStorage PERF] ${controllerName} read - ${sizeKB}KB - ${timeMs.toFixed(2)}ms`,
  );
}

function logControllerWritePerf(
  controllerName: string,
  data: unknown,
  timeMs: number,
): void {
  if (!PERF_LOGGING_ENABLED) {
    return;
  }
  const sizeKB = getSizeKB(data);
  console.warn(
    `[ControllerStorage PERF] ${controllerName} write - ${sizeKB}KB - ${timeMs.toFixed(2)}ms`,
  );
}
// ============ END PERF LOGGING ============
```

### In `get()` method - Add at start of method:

```typescript
const perfStart = performance.now();
if (PERF_LOGGING_ENABLED) {
  console.warn('[ControllerStorage PERF] getAllPersistedState started');
}
```

### In `get()` method - Add after data is loaded:

```typescript
// PERF: Log overall time and TokenListController size
if (PERF_LOGGING_ENABLED) {
  const elapsed = performance.now() - perfStart;
  console.warn(
    `[ControllerStorage PERF] getAllPersistedState complete - ${elapsed.toFixed(2)}ms`,
  );
  // Log TokenListController state size specifically
  if (data.TokenListController) {
    logControllerReadPerf(
      'TokenListController',
      data.TokenListController,
      elapsed,
    );
  }
}
```

### In `set()` method - Add logging:

```typescript
const perfStart = performance.now();

// PERF: Log TokenListController size before write
if (
  PERF_LOGGING_ENABLED &&
  isObject(data) &&
  hasProperty(data, 'TokenListController')
) {
  const tlcSize = getSizeKB(data.TokenListController);
  console.warn(
    `[ControllerStorage PERF] set() - TokenListController size: ${tlcSize}KB`,
  );
}

// ... existing set logic ...

// PERF: Log total write time (add after await local.set())
if (PERF_LOGGING_ENABLED) {
  const elapsed = performance.now() - perfStart;
  const totalSize = getSizeKB({ data, meta });
  console.warn(
    `[ControllerStorage PERF] set() complete - ${totalSize}KB - ${elapsed.toFixed(2)}ms`,
  );
}
```

### Expected Log Output

**Cold Restart:**
```
[ControllerStorage PERF] getAllPersistedState started
[ControllerStorage PERF] getAllPersistedState complete - 374.30ms
[ControllerStorage PERF] TokenListController read - 4601.13KB - 374.30ms
```

**Write (adding chain or background save):**
```
[ControllerStorage PERF] set() - TokenListController size: 4601.13KB
[ControllerStorage PERF] set() complete - 28036.55KB - 559.30ms
```

---

## 💡 Key Takeaways

1. **Write amplification eliminated**: Adding a single chain now writes
only that chain's data (~30-200KB) instead of the entire cache (~4MB)

2. **Faster incremental updates**: Per-chain writes are significantly
faster than full cache rewrites

3. **Cold restart trade-off**: Parallel file reads + getAllKeys adds
some overhead vs single file read, but the difference is minimal

4. **Onboarding improvement**: Total data written during onboarding is
reduced by avoiding cumulative rewrites

---

## ✅ PR Branch: Background Writes No Longer Include Token Cache

On this PR branch, background writes show:

```
[ControllerStorage PERF] set() - TokenListController size: 0.04KB    ← TINY! No cache!
[ControllerStorage PERF] set() complete - 23425.30KB - 481.60ms      ← ~23MB (not 28MB)
```

**Key proof**: TokenListController is only 0.04KB in the main state
because the ~4.4MB token cache is stored separately in StorageService.

---

## ⚠️ Main Branch: Continuous Background Write Amplification

During testing on main branch, we observed that the **entire 27.8MB
state is being rewritten repeatedly** even when the user is idle:

```
[ControllerStorage PERF] set() - TokenListController size: 4444.22KB
[ControllerStorage PERF] set() complete - 27877.62KB - 632.30ms
[ControllerStorage PERF] set() - TokenListController size: 4444.22KB
[ControllerStorage PERF] set() complete - 27877.62KB - 456.40ms
[ControllerStorage PERF] set() - TokenListController size: 4444.22KB
[ControllerStorage PERF] set() complete - 27877.62KB - 606.40ms
[ControllerStorage PERF] set() - TokenListController size: 4444.22KB
[ControllerStorage PERF] set() complete - 27877.59KB - 625.10ms
[ControllerStorage PERF] set() - TokenListController size: 4444.22KB
[ControllerStorage PERF] set() complete - 27877.59KB - 597.90ms
```

### Why This Happens

MetaMask has background processes that trigger state saves:
- Token balance polling
- Price updates
- Network status checks
- Account sync
- DeFi positions updates
- etc.

Each time ANY controller state changes, the **entire state** (~27.8MB)
is serialized and written to storage, including the **4.4MB
TokenListController cache that hasn't changed**.

### Impact Comparison

| Metric | This PR | Main Branch |
|--------|---------|-------------|
| State size per write | **~23MB** | **~28MB** |
| TokenListController in state | **0.04KB** | **4,601KB** |
| Token cache included in saves | ❌ No | ✅ Yes (every save) |
| Write time | ~480ms | ~550ms |

### How This PR Helps

By moving `tokensChainsCache` to StorageService:

1. **Background saves are ~18% smaller** (~23MB instead of ~28MB)
2. **Token cache only written when it actually changes** (new chain
added or cache refresh)
3. **Reduced disk I/O** - ~5MB less data serialized and written on every
background save
4. **Better SSD/storage health** - less unnecessary write cycles


## **Changelog**


CHANGELOG entry: No user facing changes; this only updates the storage
location for tokenListController.

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to this page...
2.
3.

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **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/main/.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/main/.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.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it changes how `TokenListController` persists
cached token lists and adds a state migration writing to
`browser.storage.local`, which could impact startup/migration behavior
if keys or storage operations fail.
> 
> **Overview**
> **Moves `TokenListController` token list caching to StorageService.**
The controller messenger now allows `StorageService:*` actions and
`TokenListControllerInit` fires `controller.initialize()` on startup to
load cached lists from storage (logging errors but not failing init).
> 
> **Adds migration #190 to preserve existing caches.** Migration `190`
copies `tokensChainsCache` entries into per-chain
`storageService:TokenListController:tokensChainsCache:{chainId}` keys
without overwriting existing entries, then clears the in-state cache and
bumps fixtures/snapshots to version `190`.
> 
> **Updates tests and deps for the new storage behavior.** Jest mocks
for `webextension-polyfill` are made async/shared across imports, e2e
state persistence ignores StorageService-prefixed keys, and
`@metamask/assets-controllers` is bumped to `^98.0.0`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
62be895. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
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