Skip to content

refactor: unify submitTx and submitIntent#8257

Open
micaelae wants to merge 11 commits intomainfrom
swaps4229-submitTx-strategy-refactor
Open

refactor: unify submitTx and submitIntent#8257
micaelae wants to merge 11 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

Note

Medium Risk
Refactors core transaction/intent submission paths (including approvals, batching, history keys, and polling), so regressions could affect swap/bridge execution tracking and analytics despite largely preserving behavior.

Overview
Unifies submitTx and submitIntent by moving chain/quote-specific submission logic into new strategy async-generators (evm, batch, non-evm, intent) selected by executeSubmitFlow, while submitTx now just traces, iterates yielded steps, and performs history updates/polling/metrics.

History management is tightened: history items are now added with an explicit historyKey, rekeying now takes oldKeynewKey, and intent history uses the order UID as the history key while preserving the synthetic transaction id separately.

Batch/gas handling is refactored: getAddTransactionBatchParams now accepts tradeData[] (with optional assetsFiatValues) and centralizes gasless/7702 decisions; related tests/snapshots/jest coverage ignores are updated accordingly.

Reviewed by Cursor Bugbot for commit 5b79bb8. Bugbot is set up for automated code reviews on this repo. Configure here.

@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 2 times, most recently from 38c104d to 479a9ac Compare March 24, 2026 21:21
@micaelae micaelae force-pushed the swaps4229-submitTx-strategy-refactor branch 2 times, most recently from 0d2c3b4 to 04c7e53 Compare April 8, 2026 18:57
micaelae added 3 commits April 8, 2026 12:03
batch transaction util refactor

refactor: simplify batch

tranaction fix
@micaelae micaelae force-pushed the swaps4229-submitTx-strategy-refactor branch from 04c7e53 to babd6f6 Compare April 8, 2026 19:17
@micaelae micaelae marked this pull request as ready for review April 9, 2026 20:28
@micaelae micaelae requested a review from a team as a code owner April 9, 2026 20:28
@micaelae micaelae requested a review from a team as a code owner April 9, 2026 20:28
@micaelae micaelae enabled auto-merge April 9, 2026 20:28
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 3 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5b79bb8. Configure here.

execute: (
params: SubmitStrategyParams,
) => AsyncGenerator<SubmitStepResult, void, void>;
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Exported SubmitStrategy type is never used anywhere

Low Severity

The SubmitStrategy type is defined and exported but never imported or referenced anywhere in the codebase. The actual strategy selection in executeSubmitFlow uses direct function calls rather than this interface pattern. This is dead code that adds confusion about the intended architecture.

Fix in Cursor Fix in Web

Triggered by project rule: Guidance for Bugbot

Reviewed by Cursor Bugbot for commit 5b79bb8. Configure here.

(txMetaId ? this.state.txHistory?.[txMetaId]?.location : undefined) ??
MetaMetricsSwapsEventSource.MainView,
...(eventProperties ?? {}),
location,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Metrics location priority silently changed for event tracking

Low Severity

The location resolution in #trackUnifiedSwapBridgeEvent changed priority. Previously, eventProperties?.location was preferred (the spread overrode the computed value). Now, when txMetaId is provided, history.location always wins because location is placed after the eventProperties spread. Additionally, the ternary now ignores eventProperties?.location entirely when txMetaId is truthy.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5b79bb8. Configure here.

): AsyncGenerator<SubmitStepResult, void, void> {
// TODO handle STX/batch approvals
const approvalTxId = await handleEvmApprovals(args);
approvalTxId && (await waitForTxConfirmation(args.messenger, approvalTxId));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Intent strategy omits approval trace wrapper present before

Low Severity

The submitIntentHandler calls handleEvmApprovals directly without wrapping it in traceFn(getApprovalTraceParams(...)), unlike the old submitIntent flow which traced the approval via this.#trace(getApprovalTraceParams(...), ...). The EVM strategy correctly wraps its approval in a trace, but the intent strategy does not, causing approval performance data to be lost for intent transactions.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5b79bb8. Configure here.

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.

1 participant