Skip to content

refactor: unify submitTx and submitIntent#8257

Draft
micaelae wants to merge 51 commits intomainfrom
swaps4229-submitTx-strategy-refactor
Draft

refactor: unify submitTx and submitIntent#8257
micaelae wants to merge 51 commits intomainfrom
swaps4229-submitTx-strategy-refactor

Conversation

@micaelae
Copy link
Copy Markdown
Member

@micaelae micaelae commented Mar 19, 2026

Explanation

Before

Currently, submitTx and submitIntent are separate entry points that have overlapping logic. This obscures how the flows differ and some behaviors are inconsistent, although needed by both.

  • submitTx inlines long branching for non-EVM, batch/STX/7702, and default EVM paths, with history, rekeying, polling, and analytics mixed into each branch
  • submitIntent is a second large path: intent-specific steps (approval, signing, API submit, synthetic tx) with its own history and polling/intent-manager logic
%%{init: {"themeVariables": {"noteBkgColor": "#ffffff", "noteTextColor": "#333333", "noteBorderColor": "#cccccc"}}}%%
sequenceDiagram
  participant Ext as Client
  participant BSC as BridgeStatusController

  Ext->>BSC: submitTx
  Note left of BSC: pick one flow based on quote + client <br/>flags. each branch has its own step<br/> sequence and error handling
  alt non-EVM chains
    Note right of BSC: submitApproval if Tron
    Note right of BSC: submitTrade
    Note right of BSC: setTradeMeta
    Note right of BSC: publishFailedEvent
  else gasless, STX or 7702
    Note right of BSC: submitBatch
    Note right of BSC: setTradeMeta
  else EVM
    Note right of BSC: submitApproval
    Note right of BSC: addHistoryItem
    Note right of BSC: submitTrade
    Note right of BSC: rekeyHistoryItem
    Note right of BSC: setTradeMeta
  else shared
    Note right of BSC: startPolling if Tron or bridge tx
    Note right of BSC: addHistoryItem if non-EVM or gasless
    Note right of BSC: publishCompletedEvent if non-EVM swap
  end

  Ext->>BSC: submitIntent
  Note right of BSC: submitApproval
  Note right of BSC: sign EIP-712 intent payload
  Note right of BSC: submit intent order via IntentManager
  Note right of BSC: add a synthetic tx using <br/> orderId from order submission
  Note right of BSC: addHistoryItem
Loading

After

This PR reorganizes tx submission into strategies (reduces quote-specific if conditions in the controller) and an action stream (strategies yield step results, and the controller uses those to update history, poll, and publish metrics). Each strategy yields results in their own order.

%%{init: {"flowchart": {"useMaxWidth": true, "padding": 16, "nodeSpacing": 32, "rankSpacing": 48}}}%%
flowchart TB
  subgraph top[" "]
    direction LR
    SI["submitIntent entrypoint<br/>proxies to submitTx"] --> ST["submitTx orchestrates tracing,<br/>metrics, error handling,<br/>and strategy execution"]
  end
  REG["executeSubmitFlow picks <br/> a strategy based on  <br/> quote and params"]

  subgraph s_non[" "]
    direction TB
    nn0["submitApproval"] -->  nn1["submitTrade"] --> nn2["setTradeMeta"] --> nn3["addHistoryItem"] --> nn4["startPolling"] --> nn5["publishCompletedEvent"]
  end

  subgraph s_batch[" "]
    direction TB
    bb0["submitBatch"] --> bb1["setTradeMeta"] --> bb2["addHistoryItem"]
  end

  subgraph s_intent[" "]
    direction TB
    iia["submitApproval"] --> iic["signIntentPayload"] -->  ii0["postIntentOrder"] --> iib["submitSyntheticTrade"] --> ii1["setTradeMeta"] --> ii2["addHistoryItem"] --> ii3["startPolling"]
  end

  subgraph s_evm[" "]
    direction TB
    eea["submitResetApproval"]--> eeb["submitApproval"]--> eec["addHistoryItem"] -->  ee1["submitTrade"] -->  ee2["rekeyHistoryItem"] --> ee3["setTradeMeta"]
  end

  ST --> REG
  REG --> lblNon["non-evm-strategy"]
  lblNon --> nn0
  REG --> lblBatch["batch-strategy"]
  lblBatch --> bb0
  REG --> lblIntent["intent-strategy"]
  lblIntent --> iia
  REG --> lblEvm["evm-strategy default"]
  lblEvm --> eea

  classDef stratLabel fill:#ffffff,stroke:#57606a,color:#1f2328
  class lblNon,lblBatch,lblIntent,lblEvm stratLabel
Loading

Each strategy is an async generator that yields step results for the BridgeStatusController to apply

%%{init: {"themeVariables": {"noteBkgColor": "#ffffff", "noteTextColor": "#333333", "noteBorderColor": "#cccccc"}}}%%
sequenceDiagram
  participant BSC as submitTx
  participant IDX as executeSubmitFlow
  participant STR as strategy

  BSC->>IDX: starts executing submit strategy
  IDX->>STR: selects and executes strategy (async generator)

  Note over STR,IDX: Each strategy yields a subset of these steps in different orders

  STR-->>BSC: setTradeMeta
  Note right of BSC: set the tradeMeta to be returned to the client

  STR-->>BSC: addHistoryItem
  Note right of BSC: include metadata in action payload and update state

  STR-->>BSC: rekeyHistoryItem
  Note right of BSC: update state historyItem with trade metadata

  STR-->>BSC: startPolling
  Note right of BSC: starts polling by the provided key (actionId, orderId, tradeMetaId)

  STR-->>BSC: publishCompletedEvent
  Note right of BSC: call trackUnifiedSwapBridgeEvent with txHistory key

  STR-->>IDX: generator is done
  IDX-->>BSC: return

  Note right of BSC: return tradeMeta

Loading

Example dev workflows

Add a step to some flows

  1. Extend the SubmitStepResult with a new variant describing the step
  2. Add any new controller calls to utils (avoid bridge-status-controller.ts)
  3. Handle the new type in submitTx's generator processing loop
  4. For each strategy generator that needs the step, yield the new SubmitStepResult when it should run (order matters)

Add a step that applies to all flows

  1. Add any new controller calls to utils (avoid bridge-status-controller.ts)
  2. Implement the step in submitTx, outside of the generator processing loop

Add logic that does not need BridgeStatusController state updates or events

These can stay within the relevant strategy as plain async code. No new SubmitStepResult type is needed if it doesn't touch bridge history, polling, or metrics publishing

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

@micaelae micaelae changed the title Swaps4229 submit tx strategy refactor refactor: submitTx Mar 19, 2026
@micaelae micaelae changed the title refactor: submitTx refactor: unify submitTx and submitIntent Mar 20, 2026
@micaelae micaelae force-pushed the swaps4229-submitTx-strategy-refactor branch from 7da4e79 to f9fcc48 Compare March 23, 2026 18:02
github-merge-queue bot pushed a commit that referenced this pull request Mar 24, 2026
## Explanation

Changes
- Move more code out of bridge-status-controller.ts
- Replace IntentApi.submitOrder with a pure function `postSubmitOrder`
- Update tests to serve as a baseline for the `submitTx + submitIntent`
[refactor](#8257)

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

## References

Fixes https://consensyssoftware.atlassian.net/browse/SWAPS-4229

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it refactors transaction submission, history
keying, and intent-order submission/polling paths; behavior changes
around `txHash`/action IDs and batching could affect bridge/swap
tracking if edge cases are missed.
> 
> **Overview**
> Refactors `bridge-status-controller` by moving more
transaction-handling logic into `utils/transaction` (e.g.,
`submitEvmTransaction`, `addTransactionBatch`, tx lookup/update helpers,
delegated-account check) and shifting gas-fee estimation helpers out of
`utils/gas`.
> 
> Intent order submission is changed from `IntentApiImpl.submitIntent`
to a pure `postSubmitOrder` function, and intent polling/translation now
treats missing hashes as `undefined` (not empty string) while updating
transactions via shared transaction helpers.
> 
> History handling is tightened: `StartPollingForBridgeTxStatusArgs` no
longer requires a `statusRequest`, history keys can fall back to
`originalTransactionId`, and new `utils/history` tests cover rekeying
and key selection; snapshots/tests are updated accordingly (including
added coverage for `handleNonEvmTx` response shapes and updated metrics
tracking expectations).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3ab2f3b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Base automatically changed from swaps4229-extract-controller-calls to main March 24, 2026 14:23
@micaelae micaelae force-pushed the swaps4229-submitTx-strategy-refactor branch 2 times, most recently from 9da49db to 3afcc23 Compare March 24, 2026 17:48
@micaelae micaelae changed the base branch from main to swaps4273-failed-event March 24, 2026 17:49
@micaelae micaelae force-pushed the swaps4229-submitTx-strategy-refactor branch 2 times, most recently from c3dee22 to 016db52 Compare March 24, 2026 18:16
Base automatically changed from swaps4273-failed-event to main March 24, 2026 18:22
@micaelae micaelae force-pushed the swaps4229-submitTx-strategy-refactor branch from 016db52 to 7152655 Compare March 24, 2026 18:33
rename

rename

wip

fix: merge conflict
@micaelae micaelae force-pushed the swaps4229-submitTx-strategy-refactor branch from 38c104d to 479a9ac Compare March 24, 2026 21:21
micaelae and others added 13 commits March 26, 2026 10:41
…po) (#8052)

## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

(**Context** and **Approach Motivation**)

**Context:**

With upcoming phase 1 for Tempo support, the initial approach will
leverage EIP-7702 mechanics and UX.

1. One difference vs. other chains is that **Tempo doesn't have a
concept of native token**.
--> This means that some current logic when we "fall back" to the native
token for gas fee when user has enough native balance won't work.
`excludeNativeTokenForFee` is a new parameter for signaling that
**native token should not be an option** when set to `true` and when
`gasFeeToken` is provided.

2. Since the client dApps will trigger a call `addTransactionBatch` for
some Tempo transactions - was only called internally until now - we add
the `actionId` so such transactions appear on the **Activity tab**
(transaction history). Otherwise such transactions still made it to the
state but those without `actionId` don't appear in the activity tab.

<img width="685" height="885" alt="Untitled Diagram drawio (1) (1)"
src="https://github.com/user-attachments/assets/bb7635f3-e7df-4204-8ede-8a5b8ca070fd"
/>

**Approach Motivation**

TransactionController - why a new `excludeNativeTokenForFee` argument:

This controller already supports a `gasFeeToken` argument that does
almost exactly what we want (gasless flow behavior). However there was
still behavior where:
1. Native token would override the selected `gasFeeToken` in the
TransactionController --> `excludeNativeTokenForFee` allows to say "we
do NOT want this behavior".
2. Native token would appear as selectable (or as unavailable but still
appear) in the transaction-confirmation UI when trying to select a gas
token, which doesn't make sense for chains like Tempo where there is no
concept of native token at all --> Since `excludeNativeTokenForFee` is
also included in `transactionMeta`, this allows UI to understand that
the native token shouldn't be displayed on selected when this argument
is present.
Overall, this argument is:
- Used as a generic way to say "there is no native token", in a way that
could be reused for similar chains.
- Always injected by clients - who are aware of per-chain logic - if no
such argument is injected by the client, behavior remains the same as
before this PR.

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them




<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes transaction metadata/options and alters gas-fee-token
selection behavior in `addTransaction`/batch 7702 flows, which can
affect fee payment logic across supported networks. Risk is mitigated by
being opt-in via a new optional flag and covered by added unit tests.
> 
> **Overview**
> Adds optional `excludeNativeTokenForFee` plumbing across
`addTransaction`/batch transaction request types and persists it on
`TransactionMeta` when explicitly provided.
> 
> Updates `TransactionController.addTransaction` so
`isGasFeeTokenIgnoredIfBalance` is no longer automatically `true` when
`gasFeeToken` is set; it becomes `false` when `excludeNativeTokenForFee`
is passed, ensuring the gas fee token is used regardless of native
balance.
> 
> Extends the EIP-7702 batch path (`utils/batch.ts`) to forward
`excludeNativeTokenForFee` into `addTransaction`, with new tests
covering default omission and explicit inclusion, plus controller tests
validating the new gas-fee-token behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
53b6320. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Arafet (CN - Hong Kong) <52028926+arafetbenmakhlouf@users.noreply.github.com>
## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> This PR only updates package versions, changelogs, and dependency
ranges/lockfile entries, with no functional code changes.
> 
> **Overview**
> Bumps the monorepo version to `894.0.0` and cuts releases for
`@metamask/assets-controller` (`3.3.0`) and
`@metamask/assets-controllers` (`103.1.0`), updating their changelogs
accordingly.
> 
> Propagates the new
`@metamask/assets-controller`/`@metamask/assets-controllers` versions
into dependent packages (`bridge-controller`,
`transaction-pay-controller`) and updates `yarn.lock` to match.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
cb77904. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…rt (#8264)

## Explanation

The script `scripts/generate-method-action-types.ts` generates
TypeScript action type files for controllers/services that define
`MESSENGER_EXPOSED_METHODS`. It was a monorepo-local script invoked via
`tsx ../../scripts/generate-method-action-types.ts` from 44 packages.

This PR moves it into `@metamask/messenger` as a CLI tool, keeping the
library lightweight while making the codegen reusable in other
repositories.

**What changed:**

- Add `generate-action-types/` subdirectory under
`packages/messenger/src/` with modular source files (`parse-source.ts`,
`generate-content.ts`, `check.ts`, `fix.ts`, `cli.ts`)
- Add `messenger-generate-action-types` bin entry to
`@metamask/messenger`
- `yargs` is the only runtime dependency; `@metamask/utils`,
`typescript`, and `eslint` are non-optional peer dependencies (required
for the CLI, but provided by the consuming project). The core
`Messenger` library remains lightweight.
- Recursive directory search discovers controllers/services in
subdirectories automatically, removing the need for per-subdirectory
scripts
- Update all 44 consuming packages to invoke the CLI via `tsx
../../packages/messenger/src/generate-action-types/cli.ts`
- Delete old `scripts/generate-method-action-types.ts`
- Functional tests via `execa` + `tsx` verify exact generated output for
controllers and services

**Working examples in external repos:**

- MetaMask/smart-transactions-controller#575
- MetaMask/snaps#3914

## References

- Consumer PRs:
[smart-transactions-controller#575](MetaMask/smart-transactions-controller#575),
[snaps#3914](MetaMask/snaps#3914)

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Mostly build/tooling changes, but it touches many packages and changes
the action-type generation pipeline; failures would surface as broken
scripts or mismatched generated files across the monorepo.
> 
> **Overview**
> Adds a new `@metamask/messenger` codegen CLI
(`messenger-generate-action-types`) that discovers controllers/services
with `MESSENGER_EXPOSED_METHODS` and supports `--fix` and `--check`
workflows, including optional ESLint formatting and extensive
unit/functional tests.
> 
> Migrates dozens of packages’ `generate-method-action-types` scripts to
call the new CLI entrypoint, deletes the legacy
`scripts/generate-method-action-types.ts`, and updates generated
`*-method-action-types.ts` outputs (header/JSDoc normalization and some
regenerated action unions). Also updates repo config to support the new
tooling (ESLint rule exception for the generator folder and Jest module
mapping for `@metamask/utils/node`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ca19d18. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
)

## Explanation

### Current state and why it changed

`TokenDataSource` used a **minimum occurrence count** (Tokens API
`occurrences`) to drop likely spam before merging metadata. That
heuristic is coarse: it can hide legitimate low-occurrence tokens and
still allow tokens that security scanning flags as **malicious**.

### Solution

- **Blockaid bulk token scan** — Before enriching metadata,
`TokenDataSource` calls **`PhishingController:bulkScanTokens`** on the
shared **`AssetsControllerMessenger`**, batches addresses (EVM by hex
chain id; non-EVM `token` namespace by chain name, aligned with the
multichain pattern), and **drops assets whose scan result is
malicious**. Where scanning doesn’t apply or fails, behavior stays
**fail-open** (keep the asset) as implemented.
- **Constructor** — `TokenDataSource` now takes **`(messenger,
options)`** with a **required** `AssetsControllerMessenger`, consistent
with other data sources and ensuring the phishing action is wired in
production.

### Non-obvious details

- **`numberToHex`** for EVM chain ids must come from
**`@metamask/utils`** (not `@metamask/controller-utils`) so the Blockaid
path does not throw and accidentally fail open.
- **Public package `index`** — `AssetsControllerMethodActions` and
data-source `*AllowedActions` / `*AllowedEvents` were **removed from the
root export** per repo ESLint/controller guidelines.
**`TokenDataSourceAllowedActions`** remains exported from
**`TokenDataSource`** as an explicit alias for messenger wiring.

---

## References

- PR: **#8329**
- [Updating
changelogs](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [Breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)

<!-- Add: Fixes #…, Related to #…, links to client PRs for the breaking
change if any. -->

---

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes token enrichment/filtering behavior and introduces a new
cross-controller dependency; incorrect scanning or chain/address mapping
could hide legitimate tokens or keep malicious ones (fail-open mitigates
availability).
> 
> **Overview**
> `TokenDataSource` now requires an `AssetsControllerMessenger` in its
constructor and uses it to call `PhishingController:bulkScanTokens`
(Blockaid) before merging token metadata.
> 
> The previous spam heuristic (dropping non-native tokens with low
`occurrences`) is removed; instead, assets reported as *malicious* are
filtered out of `assetsInfo`, `assetsBalance`, and `detectedAssets`,
while scan failures/non-applicable assets fail open.
> 
> This PR wires the new action into `AssetsController` allowed actions,
adds `@metamask/phishing-controller` as a dependency/TS project
reference, updates tests accordingly, and trims root exports to stop
re-exporting various `*AllowedActions/*AllowedEvents` types.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ce9be8b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

Adding this helper so we can use it in combination with `withKeyring`,
e.g:
```ts
try {
  await controller.withKeyring({ type: 'something' }, ({ keyring }) => {
    ...
  });
} catch (error) {
  if (isKeyringNotFoundError(error)) {
    await controller.addNewKeyring('something');
  }
}

// We can retry to use `withKeyring` now.
```

## References

N/A

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Small, additive change (new helper, export, and tests) with no
behavioral changes to keyring operations; risk is limited to minor API
surface/export compatibility.
> 
> **Overview**
> Adds `isKeyringNotFoundError` to `keyring-controller` as a type-guard
helper for distinguishing `KeyringController:withKeyring` “missing
keyring” failures from other errors.
> 
> Exports `KeyringControllerErrorMessage` from the package entrypoint
and adds unit coverage for the new helper; changelog is updated to
announce the new API.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
06b3fff. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

We want to have a way to access a keyring instance without the global
lock. This is needed when doing read operations on immutable data (e.g.
the mnemonics on an `HdKeyring` for Snaps derivations, derivations for
the new `MoneyKeyring`).

This mimic the use of `withKeyring` with the exception of not locking
the global controller's lock.

The "unsafe" part relates to how `unsafe { ... }` blocks work in Rust.
The caller takes the responsibility of not doing actions that could lead
to program faults. If any bugs occur because of the use of this new
action, this would truly be considered a bug, and not a problem from the
implementation of this action.

## References

N/A

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adds a new public/messenger action that bypasses the controller mutex,
which could lead to race conditions or inconsistent reads if consumers
use it for mutable keyring data. Also changes error semantics from
detailed strings to typed `KeyringControllerErrorMessage` values, which
may affect callers/tests relying on exact messages.
> 
> **Overview**
> Introduces `withKeyringUnsafe`, a new KeyringController
action/messenger handler that selects a keyring by the same selector
variants as `withKeyring` but **does not acquire the controller lock**,
intended for read-only access to immutable keyring data.
> 
> Refactors keyring selection into a shared `#selectKeyring` helper,
centralizes the “don’t return the raw keyring instance” guard, and
tightens error handling in `getKeyringForAccount` (now throwing
`NoKeyring` vs `KeyringNotFound` without embedding extra info strings).
Tests and coverage thresholds are updated accordingly, including new
test coverage ensuring `withKeyringUnsafe` avoids locking and rejects
unsafe direct keyring access.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1985fd5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Mostly release bookkeeping (version bumps, dependency bumps, lockfile
updates), but it propagates `@metamask/assets-controller@4.0.0` and
`@metamask/transaction-controller@64.0.0` which include breaking changes
that consumers must be compatible with.
> 
> **Overview**
> Bumps the monorepo version to `895.0.0` and rolls forward multiple
workspace package versions, updating their `CHANGELOG.md` entries
accordingly.
> 
> Updates inter-package dependencies to newer releases (notably
`@metamask/transaction-controller` to `64.0.0`,
`@metamask/assets-controller` to `4.0.0`, and related controller
packages), and refreshes `yarn.lock` to match.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fc4377c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

Declare the new Money keyring value, associated with
`@metamask/eth-money-keyring`.

## References

N/A

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: this only extends the `KeyringTypes` enum and updates the
package changelog, with no behavioral or security-sensitive logic
changes.
> 
> **Overview**
> Adds a new `KeyringTypes.money` enum value (`"Money Keyring"`) in
`KeyringController.ts` so consumers can reference the Money keyring type
consistently.
> 
> Updates the `@metamask/keyring-controller` changelog to announce the
new enum value.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
19e4005. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

The ConnectivityController currently defines selectors for accessing its
state directly in clients, making it inconsistent with our guidelines.

**Solution:**
- Added `selectConnectivityStatus` - simple selector that returns the
current connectivity status
- Added `selectIsOffline` - memoized selector using `reselect` that
returns `true` when offline

The selectors are exported from the package and can be used with Redux
or directly with controller state.

## References

<!-- None -->

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: adds new exported selectors and a `reselect` dependency
without changing controller behavior or state shape.
> 
> **Overview**
> Adds a new exported `connectivityControllerSelectors` API with
`selectConnectivityStatus` and a memoized `selectIsOffline` (via
`reselect`) for reading `ConnectivityControllerState`.
> 
> Updates `@metamask/connectivity-controller` to depend on `reselect`,
adds unit tests for the selectors, and documents the addition in the
package changelog.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d10a1ef. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

Money accounts will be handled in a different controller. We just filter
them out when replicating the `KeyringController` state here.

Also updated `keyringToTypeName` as this might be used in combination
with `KeyringTypes` enum, so we don't want to throw with the new
`KeyringTypes.money` value.

## References

N/A

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes account synchronization logic to ignore `KeyringTypes.money`,
which could affect account lists and selection behavior for clients that
previously saw these entries. Risk is mitigated by added unit coverage
for both `updateAccounts` and `KeyringController:stateChange` paths.
> 
> **Overview**
> **Stops `AccountsController` from treating `KeyringTypes.money` as
regular accounts.** During both full resync (`updateAccounts`) and
incremental updates from `KeyringController:stateChange`, Money keyrings
are now skipped so their addresses are not added/updated/removed in
`internalAccounts`.
> 
> Adds `isMoneyKeyringType` and updates helpers so `keyringTypeToName`
returns `"Money"` for the new enum value (instead of throwing), with
expanded unit tests and changelog notes covering the new behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
cc23100. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Gustavo Antunes <17601467+gantunesr@users.noreply.github.com>
ccharly and others added 30 commits April 7, 2026 10:16
## Explanation

Initial implementation of the `MoneyAccountController`.

## References

N/A

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Introduces new controller logic that creates and manages a new
`MoneyKeyring` via `KeyringController`, including concurrency locking
and state persistence; bugs here could affect keyring creation behavior
and account derivation for Money accounts.
> 
> **Overview**
> Adds a new package, `@metamask/money-account-controller`, implementing
`MoneyAccountController` to create and track **one Money account per
entropy source** (defaulting to the primary HD keyring) and expose
`createMoneyAccount`, `getMoneyAccount`, and `clearState` via the
messenger.
> 
> The controller integrates with `KeyringController` to find or create a
`MoneyKeyring`, defensively ensures an address exists, and uses a mutex
to prevent duplicate keyring creation under concurrent calls;
comprehensive Jest tests and package build/docs configs are included.
> 
> Repo wiring is updated to include the new package in `README.md`, root
`tsconfig` references, `CODEOWNERS`, `teams.json`, and `yarn.lock`
(including adding `@metamask/eth-money-keyring` and bumping
`@metamask/eth-hd-keyring` resolution).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1beb776. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Initial release of the new `money-account-controller`.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: this PR only updates package/changelog metadata for a
release and does not change runtime code paths.
> 
> **Overview**
> Bumps the monorepo version to `898.0.0`.
> 
> Publishes the initial `@metamask/money-account-controller` release by
setting its version to `0.1.0` and updating its `CHANGELOG.md` with a
`0.1.0` entry and release/compare links.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c866360. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

Adds SocialService — a stateless data service that wraps all social-api
endpoints with TypeScript types and superstruct response validation.
This is the data layer that a future [SocialController
(TSA-318)](https://consensyssoftware.atlassian.net/browse/TSA-318) will
consume.

We intentionally shipped the service without the controller so callers
can weigh in on what state shape and messenger actions they actually
need before we wire up BaseController. The service stands on its own and
can be used directly for testing integration with the social-api once
it's deployed.

See CHANGELOG.md for the full list of additions.

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Introduces new networking and persisted state logic (via
`BaseDataService`/`BaseController`) for social-api interactions, which
could impact consumers if schemas/endpoints differ or caching semantics
are wrong. Scoped to a new package but touches request construction,
response validation, and follow/unfollow state updates.
> 
> **Overview**
> Adds an initial implementation of `@metamask/social-controllers`
focused on social trading data and state.
> 
> Introduces `SocialService` (a `BaseDataService`) that wraps social-api
endpoints (`leaderboard`, trader profile, open/closed positions,
followers/following, follow/unfollow) with `superstruct` response
validation, consistent `HttpError` handling, and query caching
(including special-casing open-positions cache keys and forcing fresh
fetches for follow/following mutations).
> 
> Adds `SocialController` (a `BaseController`) that persists UI-facing
state for `leaderboardEntries` and `followingAddresses`, exposing
messenger actions to refresh the leaderboard, follow/unfollow traders
(with address dedupe), and sync the following list. Package exports are
updated accordingly, with comprehensive Jest coverage, new dependencies,
TS project references, and an updated changelog.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
08282b0. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: António Regadas <apregadas@gmail.com>
Co-authored-by: Antonio Regadas <antonio.regadas@consensys.net>
## Explanation

Releases social-controller: #8337

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Release metadata only (version/changelog updates) with no functional
code changes. Low risk aside from potential publishing/versioning
mishaps.
> 
> **Overview**
> Prepares the `899.0.0` release by bumping the root monorepo version.
> 
> Publishes `@metamask/social-controllers` as `0.1.0` by updating its
package version and finalizing the changelog with a `0.1.0` section and
correct compare/release links.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1741952. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

This refactor removes the proactive bulk-fetch pattern from
`ComplianceController` and `ComplianceService`.

**Before:** On initialisation, `init()` eagerly fetched the full blocked
wallets list from `GET /v1/blocked-wallets` and persisted all addresses
in `state.blockedWallets`. This meant potentially thousands of
OFAC/sanctioned addresses were stored in client state, refreshed on a
configurable interval, and used as the primary lookup source for
`selectIsWalletBlocked`.

**After:** The controller only performs on-demand per-address API checks
(`checkWalletCompliance` / `checkWalletsCompliance`). Results are cached
in `walletComplianceStatusMap` keyed by address. If a subsequent API
call for the same address fails, the cached result is returned as a
fallback. If no cached result exists, the error is re-thrown.

### Changes

**`ComplianceController`**
- Removed `state.blockedWallets` and `state.blockedWalletsLastFetched`
fields
- Removed `init()`, `updateBlockedWallets()`, `#isBlockedWalletsStale()`
and `#blockedWalletsRefreshInterval`
- `checkWalletCompliance` and `checkWalletsCompliance` now wrap the API
call in try/catch — on failure they fall back to the per-address cache,
re-throwing only when no cached entry exists

**`ComplianceService`**
- Removed `updateBlockedWallets()` method and the `GET
/v1/blocked-wallets` endpoint integration

**`selectors`**
- `selectIsWalletBlocked` now reads solely from
`walletComplianceStatusMap`; the `selectBlockedWallets` intermediate
selector is removed

**`types`**
- Removed `BlockedWalletsInfo` type

**Messenger action types / index**
- Removed `ComplianceControllerInitAction`,
`ComplianceControllerUpdateBlockedWalletsAction`, and
`ComplianceServiceUpdateBlockedWalletsAction`

## References

N/A

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by updating changelogs
for packages I've changed
- [ ] I've introduced breaking changes in this PR and have prepared
draft pull requests for clients and consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> Breaking public API/state changes remove blocklist fetching and alter
`selectIsWalletBlocked` to depend solely on per-address cached checks,
which can change behavior when the API is down. Consumers must update
persisted-state migrations and remove calls to deleted
controller/service methods.
> 
> **Overview**
> Removes the proactive full blocklist fetch/caching flow, shifting
compliance to **on-demand per-address checks** (`checkWalletCompliance`
/ `checkWalletsCompliance`) with a per-address cache used only as a
fallback when the API is unavailable.
> 
> This is a **breaking change**: `ComplianceControllerState` drops
`blockedWallets`/`blockedWalletsLastFetched`, the controller’s
`init()`/`updateBlockedWallets()` methods and
`blockedWalletsRefreshInterval` option are removed, and
`ComplianceService:updateBlockedWallets` (and `GET /v1/blocked-wallets`)
plus related exported action/types (`BlockedWalletsInfo`, init/update
action types) are deleted. `selectIsWalletBlocked` now reads solely from
`walletComplianceStatusMap`, and tests/changelog are updated
accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
148c209. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

This release bumps `@metamask/compliance-controller` from `1.0.2` to
`2.0.0`.

The major version bump is required due to breaking changes in the
compliance controller — see the
[changelog](https://github.com/MetaMask/core/blob/release/900.0.0/packages/compliance-controller/CHANGELOG.md)
for full details.

### Packages released

| Package | From | To | Type |
|---|---|---|---|
| `@metamask/compliance-controller` | `1.0.2` | `2.0.0` | major |

### Summary of changes

**Added**
- `generate-action-types` CLI tool available as a subpath export via the
`@metamask/messenger` bump
([#8264](#8264))

**Breaking changes**
- Removed proactive bulk-fetch pattern from `ComplianceController` and
`ComplianceService`
([#8365](#8365))
- `state.blockedWallets` and `state.blockedWalletsLastFetched` removed —
consumers with persisted state must drop these fields on migration
  - `init()`, `updateBlockedWallets()` controller methods removed
  - `blockedWalletsRefreshInterval` constructor option removed
- `ComplianceControllerInitAction`,
`ComplianceControllerUpdateBlockedWalletsAction`,
`ComplianceServiceUpdateBlockedWalletsAction`, `BlockedWalletsInfo`
removed from public API
- `checkWalletCompliance` / `checkWalletsCompliance` now fall back to
the per-address cache on API failure
- `selectIsWalletBlocked` now reads solely from
`walletComplianceStatusMap`

## References

- [#8365](#8365) —
refactor(compliance): remove initial block wallets call

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by updating changelogs
for packages I've changed
- [x] I've introduced breaking changes in this PR and have prepared
draft pull requests for clients and consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Release-only changes, but it publishes a new major
`@metamask/compliance-controller` version with breaking API/state
removals that downstream consumers must migrate to.
> 
> **Overview**
> Bumps the monorepo version to `900.0.0` and releases
`@metamask/compliance-controller` `2.0.0`.
> 
> Updates the compliance-controller changelog to document the
**breaking** removal of the blocked-wallets bulk-fetch flow and related
public API/state fields, and adjusts the `[Unreleased]`/`[2.0.0]`
compare links accordingly.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7060084. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: cryptodev-2s <109512101+cryptodev-2s@users.noreply.github.com>
## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

The new `messenger-generate-action-types` tool in the `messenger`
package uses ESLint under the hood to format a generated file. When we
added this tool we didn't want to depend directly on ESLint; we wanted
to use the same version as the consuming project instead (in order to
prevent lint violations). Our solution was to add `eslint` as a peer
dependency.

However, doing this seems to cause Yarn to see `eslint` as a
"production" dependency, even if it's defined as a dev dependency in the
consuming project. In the extension in particular, this is causing `yarn
npm audit` to flag dependencies of `eslint` it previously did not flag.

As a quick fix, we remove `eslint` as a peer dependency. This doesn't
mean the dependency on ESLint goes away — consuming projects will not be
able to run `messenger-generate-action-types` unless ESLint is added —
but we accept this as a tradeoff for now. In the future, we will
implement a better fix by moving the CLI to a different package.

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: dependency metadata-only change that removes `eslint` from
`peerDependencies`, primarily affecting consumer install/audit behavior
rather than runtime code paths.
> 
> **Overview**
> Removes `eslint` from `@metamask/messenger` `peerDependencies` (and
the corresponding `yarn.lock` metadata) to avoid consumer audit/install
failures when using ESLint 8.x.
> 
> Adds an *Unreleased* changelog entry documenting the fix.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
d21a2af. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This release includes 1 package:

- `@metamask/messenger` 1.1.1

See changelog for more:
https://github.com/MetaMask/core/blob/main/packages/messenger/CHANGELOG.md#unreleased

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Primarily a dependency/version bump across packages; behavior changes
are confined to `@metamask/messenger` and should be low risk aside from
any downstream impact of the updated library.
> 
> **Overview**
> Bumps the monorepo version to `901.0.0` and releases
`@metamask/messenger` `1.1.1` (changelog notes dropping the `eslint`
peer dependency to avoid consumer audit issues).
> 
> Updates a large set of internal packages’ `package.json` dependencies
and `CHANGELOG.md` entries to reference `@metamask/messenger` `^1.1.1`,
with corresponding `yarn.lock` refresh.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
345622a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

Since the `:stateChange` event was added to BaseController, we have
added a
[guideline](https://github.com/MetaMask/core/blob/a618f17bf4c037d9f93bbfbe0c70f56f00478d45/docs/code-guidelines/controller-guidelines.md#use-standard-naming-scheme-for-event-identifiers)
which suggests that engineers use past tense for all event names. This
commit updates `BaseController` to align with that guideline. To
maintain backward compatibility, we add a new event, `:stateChanged`,
rather than replacing the existing event. We also deprecate subscribing
to or delegating `:stateChange` by adding some custom ESLint rules.

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

We are about to add the `:cacheUpdate` to `BaseDataService`
[here](#8039), so I thought I'd
deprecate `BaseController:stateChange` so we can add
`BaseDataService:cacheUpdated` instead.

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches `@metamask/base-controller`’s core event contract by
publishing an additional state event and widening event types, which
could affect consumers’ subscriptions and test expectations. Backward
compatibility is maintained, but the new ESLint restriction may
introduce CI/lint failures in downstream code until migrated.
> 
> **Overview**
> `BaseController` now publishes a new `${ControllerName}:stateChanged`
event (with initial payload support) alongside the existing
`${ControllerName}:stateChange`, and introduces the
`ControllerStateChangedEvent` utility type while marking
`ControllerStateChangeEvent` as deprecated.
> 
> Repo-wide guidance and examples are updated to prefer `:stateChanged`,
tests are adjusted to account for the additional publish behavior, and
ESLint adds a custom `no-restricted-syntax` check to flag
`subscribe`/`delegate` usage of `:stateChange` (with updated
`eslint-suppressions.json` entries to cover existing violations).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9b044ed. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

When contributors add new packages, they sometimes forget to run `yarn
update-readme-content` to regenerate the list of packages and dependency
graph in the README. This commit adds a `--check` option to the
`update-readme-content` script and adds it to the lint pipeline to
ensure that this never happens again.

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

(This keeps bothering me)

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Medium risk because it adds a new lint/CI gate that can fail builds
when README generation drifts, and renames the yarn script used by
tooling (e.g., `create-package`) which could break existing contributor
workflows if not adopted everywhere.
> 
> **Overview**
> Ensures the generated README sections (workspace package list +
Mermaid dependency graph) stay in sync by adding a `--check` mode to
`scripts/update-readme-content.ts` and wiring it into the main `lint`
script and CI workflow.
> 
> Renames the yarn entrypoints to `readme-content:update` /
`readme-content:check` and updates `create-package` postprocessing/tests
accordingly. Updates `README.md` generated dependency graph content to
reflect current workspace dependencies.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f48ac1e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…t own data lifecycle (#8354)

## Explanation

Payment methods, providers, and tokens were being fetched redundantly
from two independent paths: the controller's `fireAndForget` calls
(inside `setSelectedToken`, `setSelectedProvider`, and `setUserRegion`)
and React Query on the mobile side. This caused 2–3 duplicate API calls
per user action, with a ~10s spinner on the `/payments` endpoint due to
cold DB connection pooling.

This PR removes all `fireAndForget` data-fetching side effects from the
controller. The mobile client (React Query + RampsBootstrap) is now the
single owner of when providers, tokens, and payment methods are fetched.
The controller only manages state updates and selections.

Changes:

1. **`#runInit` (geolocation fix)** — `forceRefresh` no longer overrides
a persisted `userRegion` with the geolocation endpoint. Geolocation is
only used to seed the initial region when `userRegion` is null.

2. **`setSelectedToken`** — Removed
`fireAndForget(getPaymentMethods(...))` and
`resetResource('paymentMethods')`. Token change no longer triggers
payment methods fetch or clears payment methods state. Payment methods
are provider-scoped, not token-scoped.

3. **`setSelectedProvider`** — Removed
`fireAndForget(getPaymentMethods(...))`,
`resetResource('paymentMethods')`, and `tokenSupportedByProvider` gate.
Now accepts a full `Provider` object (not just ID) to avoid dependency
on `state.providers.data` being populated. Silently ignores when
provider ID is not found instead of throwing.

4. **`setUserRegion`** — Removed `fireAndForget(getTokens(...))` and
`fireAndForget(getProviders(...))`. The mobile client handles all data
fetching via React Query (providers, payment methods) and direct
controller calls (tokens) from RampsBootstrap.

5. **`setSelectedPaymentMethod`** — Now accepts a full `PaymentMethod`
object (not just ID) to avoid dependency on `state.paymentMethods.data`
being populated. Silently sets `null` when payment method ID is not
found instead of throwing.

6. **`getPaymentMethods` response handler** — Always selects the first
(highest-scored) payment method when new data arrives, preventing
dead-end states where a payment method with no quotes stays selected
after provider switch.

7. **`#fireAndForget`** — Removed (no remaining callers).

8. **`executeRequest` generation counter** — Added
`#pendingResourceGeneration` map to prevent stale in-flight requests
from corrupting `isLoading` state. When `setUserRegion` resets dependent
resource counts, the generation is bumped. Orphaned finally blocks from
the previous generation skip their decrement instead of prematurely
clearing `isLoading`.

## Link to metamask-mobile

Depends on mobile PR:
[MetaMask/metamask-mobile#28224](MetaMask/metamask-mobile#28224)

## References

[TRAM-3398](https://consensyssoftware.atlassian.net/browse/TRAM-3398)

## Changelog

CHANGELOG entry: See `packages/ramps-controller/CHANGELOG.md` Unreleased
section.

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Behavior changes in `RampsController` selection/region flows (no
longer auto-fetching or clearing dependent data) could affect consumers
that relied on controller-side side effects. Adds new stale-request
invalidation for `executeRequest`, which impacts loading/error state
handling across resources.
> 
> **Overview**
> **Shifts ramps data lifecycle ownership to the client** by removing
controller-side `fireAndForget` fetching from `setUserRegion`,
`setSelectedToken`, and `setSelectedProvider`, and by no longer clearing
`paymentMethods` on token/provider changes.
> 
> `setSelectedProvider` and `setSelectedPaymentMethod` now accept either
an ID or a full object and **stop throwing when backing resource data
isn’t loaded/not found** (silently leaving selection `null`). `init` is
fixed to **never override a persisted `userRegion` with geolocation**,
even on `forceRefresh`.
> 
> Request tracking is hardened by adding a per-resource generation
counter so stale in-flight requests can’t incorrectly decrement
ref-counted `isLoading` after dependent-resource resets; tests are
updated/added to cover these races and the new selection semantics.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7073fe5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Releases `@metamask/ramps-controller@13.0.0` and
`@metamask/transaction-pay-controller@19.0.3`, including dependency
alignment for the ramps major release.

**What changed:**

- **`@metamask/ramps-controller` `13.0.0`** — Includes a documented
breaking change: controller-side implicit fetching was removed
(`setSelectedToken`, `setSelectedProvider`, `setUserRegion` no longer
trigger dependent fetches).
- **Client migration expectation** — Consumers must trigger `getTokens`,
`getProviders`, and `getPaymentMethods` from the client layer (e.g.,
hooks/effects/React Query) when region/provider/token changes.
- **`@metamask/transaction-pay-controller` `19.0.3`** — Updated to align
with `@metamask/ramps-controller` `^13.0.0` and avoid version
skew/duplicate ramps-controller copies in downstream dependency trees.
- **Release metadata updates** — Monorepo release/version and lockfile
updates associated with this release batch.

**What stays untouched:**

- No intended behavioral changes in
`@metamask/transaction-pay-controller` beyond dependency/version
alignment.

**Dependencies:**

- `@metamask/transaction-pay-controller` now depends on
`@metamask/ramps-controller` `^13.0.0`.
- Changelogs:
- `@metamask/ramps-controller`:
https://github.com/MetaMask/core/blob/main/packages/ramps-controller/CHANGELOG.md#unreleased
- `@metamask/transaction-pay-controller`:
https://github.com/MetaMask/core/blob/main/packages/transaction-pay-controller/CHANGELOG.md#unreleased
## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk administrative change that only updates ownership mappings
for `ramps-controller`; no runtime code paths are modified.
> 
> **Overview**
> Renames the owning group for `ramps-controller` from *Ramp Team* to
**Money Movement Team**.
> 
> Updates `.github/CODEOWNERS` and `teams.json` so reviews and automated
workflows route `ramps-controller` (including its
`package.json`/`CHANGELOG.md`) to `@MetaMask/money-movement` /
`team-money-movement` instead of the previous ramp ownership.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7a918fa. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Yu-Gi-Oh! <54774811+imyugioh@users.noreply.github.com>
…8378)

## Explanation

The `generate-action-types` CLI tool currently lives inside
`@metamask/messenger`. Consumers may use different ESLint or TypeScript
versions, which complicates usage when these are peer dependencies. This
PR extracts the CLI into its own dedicated package
(`@metamask/messenger-cli`) so consumers can install it as a
devDependency with their own ESLint/TypeScript versions.

### Changes

- **New `@metamask/messenger-cli` package** with all CLI source files
and tests (100% coverage).
- `eslint` and `typescript` are peer dependencies (uses the project's
versions to avoid formatting mismatches).
  - `@metamask/utils` and `yargs` are regular dependencies.
  - CLI-only package — no public API exports, no typedoc.
- Binary: `messenger-action-types --generate` / `messenger-action-types
--check`
- **`@metamask/messenger` is unchanged for consumers** (non-breaking).
The existing CLI and binary remain, with a deprecation warning pointing
to the new package.
- **Per-package scripts** renamed to `messenger-action-types:generate`
and `messenger-action-types:check` (matching
`changelog:update`/`changelog:validate` pattern).
- **Removed `tsx` devDependency** from ~49 consumer packages (no longer
needed per-package).
- **Updated root scripts** to `messenger-action-types:check` and
`messenger-action-types:generate`.
- **Updated CI, docs, and metadata** (`lint-build-test.yml`,
`controller-guidelines.md`, `teams.json`, `CODEOWNERS`,
`eslint.config.mjs`, `yarn.config.cjs`).

This package will also serve as the home for `@metamask/messenger-docs`
in a follow-up, consolidating all messenger CLI tooling in one place.

## References

- Related to #8264

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by updating changelogs
for packages I've changed
- [ ] I've introduced breaking changes in this PR and have prepared
draft pull requests for clients and consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Mostly build/dev-tooling changes, but it rewires lint/CI scripts and
per-package workflows; mistakes could break generation checks or CI
across many workspaces.
> 
> **Overview**
> Introduces a new workspace package, `@metamask/messenger-cli`, that
provides the `messenger-action-types` binary to **generate** and
**check** `*-method-action-types.ts` files (including source discovery,
JSDoc extraction, optional ESLint formatting, and full test coverage).
> 
> Updates the monorepo to use the new CLI everywhere: root
`lint`/`lint:fix` and CI now run `messenger-action-types:*`, and many
workspace `package.json` scripts are renamed from
`generate-method-action-types` to
`messenger-action-types:generate`/`:check` pointing at the new CLI.
> 
> Marks the old `@metamask/messenger` `messenger-generate-action-types`
CLI as **deprecated** via a runtime warning, and updates
docs/metadata/config (`README`, controller guidelines, `CODEOWNERS`,
`teams.json`, `eslint.config.mjs`, `tsconfig*`, `yarn.config.cjs`) to
register the new package and its build exceptions.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ab18925. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Elliot Winkler <elliot.winkler@gmail.com>
## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Versioning-only changes: bumps the monorepo version and marks
`@metamask/messenger-cli` as `0.1.0` with a corresponding changelog
entry. Low risk because it does not modify runtime code or behavior.
> 
> **Overview**
> Bumps the monorepo version to `903.0.0`.
> 
> Publishes the initial `@metamask/messenger-cli` release by setting its
version to `0.1.0` and updating its `CHANGELOG.md` with the `0.1.0`
section and release/compare links.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
555b1da. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…#7284)

## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->
The metadata service now supports a `dataType` column for categorizing
secret data (PrimarySrp, ImportedSrp, ImportedPrivateKey). This enables
clients to distinguish between different types of backed-up secrets

Changes include:
- Add `dataType` parameter to insert operations
- Add `updateSecretDataItem` and `batchUpdateSecretDataItems` for
updating existing items
- Update `fetchAllSecretData` to return storage metadata (`itemId`,
`dataType`) alongside secret data
- Refactor `SecretMetadata` to separate local metadata from
storage-level metadata

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

https://consensyssoftware.atlassian.net/browse/SL-350

## Checklist

- [x] I've updated the test suite for new or updated code as appropriate
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [x] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/contributing.md#updating-changelogs)
- [x] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Introduces breaking API changes and new migration logic that updates
remote secret metadata and changes secret ordering/validation, so
regressions could affect backup/restore correctness for existing users.
> 
> **Overview**
> Secret backups now carry a storage-level `dataType`
(`PrimarySrp`/`ImportedSrp`/`ImportedPrivateKey`) via
`@metamask/toprf-secure-backup@^1.0.0`, and `addNewSecretData` is
**breaking**: it accepts `dataType: EncAccountDataType` (rejecting
`PrimarySrp`) and persists that classification when adding items.
> 
> `fetchAllSecretData` now consumes the SDK’s richer
`FetchedSecretDataItem` shape, returns `SecretMetadata` enriched with
`itemId`/`dataType`/`createdAt`/`storageVersion`, and changes
ordering/validation to use `PrimarySrp`-first sorting with TIMEUUID
timestamp extraction (fixing previous lexicographic TIMEUUID sorting).
> 
> Adds migration plumbing: controller state gains persisted
`migrationVersion` plus `runMigrations`/`setMigrationVersion`, with a
`#migrateDataTypes` routine that updates legacy items’ `dataType`
(single vs batch updates) and marks migration completion;
`SecretMetadata` is refactored accordingly (removing old
batch/parse/sort helpers and `version` in favor of `storageVersion`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
7141349. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ster asset loading (#8383)

- Split getAssets pipeline into a fast awaited path (AccountsApi +
StakedBalance) and a parallel background path (Snap + RPC) to reduce
perceived latency on unlock and onboarding
- Batch PriceDataSource and TokenDataSource API requests in chunks of 50
using reduceInBatchesSerially to avoid DynamoDB 100-item batch limit
errors
- Filter synthetic slip44:NUMBER-* staking-position asset IDs from Price
API calls
- Filter EVM ERC-20 tokens by occurrences >= 3 (treat missing
occurrences as 0)
- Fix ESLint "in" operator violation in PriceDataSource
isValidMarketData`

## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes core asset-loading flow to run RPC/Snap in a fire-and-forget
background pipeline and alters token/price enrichment behavior
(especially in RPC-only mode), which could affect state consistency and
displayed balances/prices if regressions occur.
> 
> **Overview**
> **Speeds up perceived asset loading** by splitting
`AssetsController.getAssets` into an awaited *fast* pipeline (Accounts
API + staked balance → detection → token/price) and a *background*
Snap/RPC pipeline that merges results into state asynchronously.
> 
> **Tightens RPC-only behavior**: when basic functionality is disabled,
token/price enrichment is skipped in both `getAssets` and
`handleAssetsUpdate`, and `setSelectedCurrency` no longer triggers a
price refresh.
> 
> **Reduces backend/API failure risk** by batching `PriceDataSource`
spot-price requests and `TokenDataSource` metadata requests into chunks
of 50, and by filtering synthetic `slip44:<number>-*` staking-position
asset IDs out of Price API calls; token spam filtering is updated to
require `occurrences >= 3` for EVM ERC-20s (missing treated as 0) while
non-EVM `token` assets continue to use Blockaid. Tests/changelog are
updated accordingly.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
32d17b5. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

Re-enable Across for perps deposits by allowing the specific quote-time
perpsDeposit route and normalizing Arbitrum USDC targets to Across’s new
HyperCore USDC-PERPS direct-deposit token. Keep the change limited so
only the supported perps deposit flow bypasses Across’s same-chain
rejection and same-token quote skipping.

At quote-build time, transaction pay still represents the required asset
as Arbitrum USDC, so Across sees sourceChainId === targetChainId and
“same token” even though the real destination we need to quote is
HyperCore 1337 + 0x2100...0000. If we do not bypass those checks for
this narrow case, the request is filtered out before we ever rewrite it
into the actual Across direct-deposit route.

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes Across strategy routing and quote normalization for
`perpsDeposit`, including chain/token rewriting and decimal conversion,
which could impact deposit quoting/execution if the detection logic is
wrong. Scope is limited to a narrow perps-deposit shape and is covered
by new unit tests.
> 
> **Overview**
> Re-enables **Across quoting for a narrow `perpsDeposit` flow** by
detecting supported Arbitrum USDC perps deposits and rewriting the quote
request into Across’s HyperCore USDC-PERPS direct-deposit route
(chain/token swap plus 6→8 decimal `targetAmountMinimum` scaling).
> 
> Updates Across handling to bypass same-chain rejection and “same
token” quote skipping for this specific case, including returning a
simple destination (no actions, recipient=`from`) for supported perps
deposits. Adds focused tests and a changelog entry for the new Across
perps deposit support.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
99a8585. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ng same-token filter for HyperLiquid source (#8387)

## Explanation

When a user initiates a perps withdrawal targeting Arbitrum USDC, the
`calculatePostQuoteSourceAmounts` function filters out the source token
because it matches the destination token (both are Arbitrum USDC on
chain `0xa4b1`). This prevents any Relay quote requests from being
built, so `calculateTotals` falls back to computing raw gas cost on the
dummy Arbitrum transaction — producing an absurd ~$16M transaction fee.

The relay strategy's `normalizeRequest()` would have renormalized the
source from Arbitrum USDC to HyperCore USDC (chain `0x539`, 8 decimals),
making them distinct tokens. But this normalization happens downstream
of the source-amounts filter, so it never gets a chance to run.

Withdrawing to a different token (e.g. BNB) works fine because
`isSameToken` returns false, so the filter doesn't apply and the Relay
quote is fetched normally.

Fixes https://consensyssoftware.atlassian.net/browse/CONF-1150

## Changes

- Pass `isHyperliquidSource` from `transactionData` into
`calculatePostQuoteSourceAmounts`
- Bypass the `isSameToken` filter when `isHyperliquidSource` is true,
since the relay strategy will renormalize the source to HyperCore USDC
(a different chain)
- Add unit tests for the new behavior and confirm existing behavior is
preserved

## References

- Affected flow: Perps → Withdraw → Receive USDC (Arbitrum)
- Root cause: `isSameToken(ArbitrumUSDC, ArbitrumUSDC)` → `true` →
source amount filtered out → no quotes → fallback to raw transaction gas
cost

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Adjusts post-quote source-amount filtering logic for
`isHyperliquidSource`, which affects whether Relay quotes are requested
and therefore impacts fee/quote calculation for withdrawals. Scoped
behind a specific flag, but regressions could alter quoting behavior for
post-quote flows.
> 
> **Overview**
> Fixes HyperLiquid *post-quote (withdrawal)* flows where the source
token could be incorrectly dropped as “same as destination,” preventing
Relay quote requests and leading to wildly incorrect fee estimates.
> 
> `updateSourceAmounts` now passes `transactionData.isHyperliquidSource`
into `calculatePostQuoteSourceAmounts`, which bypasses the
same-token/same-chain filter when that flag is true. Adds unit tests
covering the new HyperLiquid behavior and preserving the existing
same-token filtering when the flag is false, and records the fix in the
changelog.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
fbcb2ee. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Signed-off-by: dan437 <80175477+dan437@users.noreply.github.com>
## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes token detection and RPC metadata behavior by replacing
`TokenListController:getState` with live Tokens API fetches (with
caching/fallback), which can affect detected tokens and metadata
availability when the API is slow or unavailable.
> 
> **Overview**
> **Token detection now pulls its token list from the Tokens API instead
of `TokenListController`.** `TokenDetector` takes a new
`TokensApiClient`, fetches `/v3/chains/{chain}/assets`, caches results
per chain, and falls back to stale cache on API errors (logging
failures).
> 
> `RpcDataSource` and `AssetsController` drop
`TokenListController:getState` from allowed actions and remove
token-list-based ERC-20 metadata fallbacks; unknown ERC-20s are omitted
from `assetsInfo` until downstream enrichment. Tests/fixtures are
updated accordingly, and a new `TokensApiClient` (plus unit tests) is
added and exported.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
9baa7da. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

The goal of this PR is to add a `submissionMethod` property in the
TransactionMetadata object in order to record how the transaction was
submitted to the network and add it to the metrics. This datapoint can
be recording at submission in the
https://github.com/MetaMask/metamask-extension/blob/main/app/scripts/controller-init/confirmations/transaction-controller-init.ts

Draft PR on extension to demonstrate the use case:
MetaMask/metamask-extension#41465

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: this is a type-only change adding an optional metadata field
and enum export, with no behavioral changes to transaction processing.
> 
> **Overview**
> Adds an optional `submissionMethod` field to `TransactionMeta` along
with a new `TransactionSubmissionMethod` enum (currently `sentinel_stx`
and `sentinel_relay`) so clients can persist how a transaction was
submitted.
> 
> Re-exports `TransactionSubmissionMethod` from the package entrypoint
and documents the addition in the `transaction-controller` changelog.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
dd12d37. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## Explanation

<!--
Thanks for your contribution! Take a moment to answer these questions so
that reviewers have the information they need to properly understand
your changes:

* What is the current state of things and why does it need to change?
* What is the solution your changes offer and how does it work?
* Are there any changes whose purpose might not obvious to those
unfamiliar with the domain?
* If your primary goal was to update one package but you found you had
to update another one along the way, why did you do so?
* If you had to upgrade a dependency, why did you do so?
-->

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Moderate risk because it changes how balance/detection/staked-balance
update callbacks propagate failures, potentially masking bugs but
preventing unhandled rejections from breaking polling ticks or
subscriptions.
> 
> **Overview**
> Improves resilience of `assets-controller` update pipelines by
**catching and logging errors inside subscription/polling callbacks**
instead of letting them throw/reject.
> 
> `AssetsController` now guards `onActiveChainsUpdated`, and
`RpcDataSource`/`StakedBalanceDataSource` wrap balance, detection, and
staked-balance update handlers so poll ticks can’t fail due to uncaught
exceptions or unhandled promise rejections.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
db04572. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…ger (#8367)

This updates the following controllers to expose all methods through the
messenger in a standardised way:

- `BridgeController`.
- `BridgeStatusController`.

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: changes are limited to new TypeScript action type exports, a
build-time generation script dependency, and test refactoring; no bridge
runtime logic is modified.
>
> **Overview**
> Adds an auto-generated `bridge-controller-method-action-types.ts` that
defines and exports **per-method** messenger action types (e.g.,
`BridgeControllerFetchQuotesAction`) for all public `BridgeController`
methods, and documents/deprecates the older aggregated action types in
the changelog.
>
> Updates `package.json` to support generating these types via a new
`generate-method-action-types` script (adding `tsx`), and refactors the
`BridgeController` SSE tests to exercise the controller through a real
`@metamask/messenger` instance (`rootMessenger.call(...)`) instead of a
hand-rolled messenger mock.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
56740c7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
This reverts commit f59258e.
batch transaction util refactor
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.