Skip to content

Commit afb989c

Browse files
authored
feat: add support for batch sell in quote status manager (#9514)
## Explanation **What is the current state of things and why does it need to change?** The `QuoteStatusManager` reports each quote's on-chain status (`SUBMITTED` → `FinalizedSuccess`/`FinalizedFailed`) to the backend keyed by a single source transaction hash and `txMetaId`. This worked for the existing single-transaction submission paths, but batch sell flows (EIP-7702 delegated accounts and nested/atomic batch transactions, handled by `submitBatchSellHandler` in `strategy/batch-sell-strategy.ts`) can submit *multiple* quotes under a single batch transaction. Previously there was no way to correlate all of the quotes in a batch to the one transaction hash that actually executes them, so their status reporting and finalization couldn't be tracked correctly as a group. **What is the solution your changes offer and how does it work?** `reportSubmitted`/`reportFinalised` on `QuoteStatusManager` (`quote-status-manager/quotes-status-manager.ts`) now correlate entries by shared `txMetaId` rather than assuming a 1:1 quote-to-transaction relationship: - When a batch sell is submitted, `submitBatchSellHandler` determines whether the batch produced a single transaction (atomic 7702/nested batch) or multiple independent transactions (e.g. STX/`sendBundle`), since that determines how the quotes should be tracked (`isSingleBatchTx` check against unique `txMeta.id` values). - For a single-tx batch, every quote sharing that batch is reported as `SUBMITTED` under the same source transaction hash and `txMetaId`, and a parent history item plus per-quote nested history items are recorded. - `QuoteStatusEntryStore.getAllByTxMetaId` allows `reportFinalised` to look up *all* entries sharing a `txMetaId` and transition/finalize them together once that shared transaction confirms or fails, instead of only handling a single entry. - For multi-tx batches, each quote keeps its own transaction hash/history item, preserving existing single-quote behavior. **Are there any changes whose purpose might not be obvious to those unfamiliar with the domain?** - The distinction between "atomic 7702/nested batch" (one tx) vs. "STX/sendBundle batch" (many txs) is why `submitBatchSellHandler` counts *unique* `txMeta.id`s rather than trusting `is7702Tx` alone, a delegated (7702) account can still produce multiple transactions via STX, so `is7702Tx` being true doesn't guarantee a single shared hash. - `reportSubmitted` intentionally no-ops (drops) a submission if the quote has already moved past `Submitted` for that quote id, this guards against late/duplicate `SUBMITTED` calls racing with finalization in the batch scenario, since the backend would reject a `SUBMITTED` call for an entry already in a terminal state. ## References https://consensyssoftware.atlassian.net/browse/SWAPS-4705 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes backend quote-status lifecycle for batch sells and multi-entry finalization by txMetaId; behavior is heavily tested but incorrect grouping could mis-report quote states. > > **Overview** > Extends **quote-status reporting** so **batch sell** flows (atomic EIP-7702 / nested batch with **one** on-chain transaction) can send **`SUBMITTED`** and finalization for **every quote** under the **same** source tx hash and **`txMetaId`**. > > **`#reportSubmittedOnce`** now resolves quotes from a batch parent’s **`quoteIds`** (child history keys → real quote ids) and calls **`reportSubmitted`** for each, with the existing **`reportedSubmittedTxHash`** guard still applying once per parent. Startup backfill treats parents with **`quoteIds`** as eligible even when the parent has no single **`quoteId`**. > > **`QuoteStatusEntryStore.getAllByTxMetaId`** and **`QuoteStatusManager.reportFinalised`** finalize **all** store entries that share a **`txMetaId`**, skipping entries already in a terminal state so duplicate finalization stays safe. > > **`submitBatchSellHandler`** only builds the parent + nested history shape when the batch produced **one** distinct **`txMeta.id`** (`isSingleBatchTx`); multi-tx batches (e.g. STX/sendBundle) keep per-quote tracking. **`BridgeHistoryItem`** docs clarify **`quoteIds`** vs **`quoteId`**. > > Tests cover batch submit/confirm/fail, startup seeding, rekey edge cases, and store/manager batch finalization. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit b4cd9f4. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent e2d807c commit afb989c

10 files changed

Lines changed: 659 additions & 72 deletions

packages/bridge-status-controller/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Support batch sell (EIP-7702/nested batch) transactions in the quote-status flow, so every quote submitted under a single batch transaction is reported to the backend. All quotes sharing one batch source transaction are reported as `SUBMITTED` under the shared source transaction hash and `txMetaId`, and are finalized together when that transaction confirms or fails. ([#9514](https://github.com/MetaMask/core/pull/9514))
13+
1014
## [74.2.0]
1115

1216
### Added

packages/bridge-status-controller/src/__snapshots__/bridge-status-controller.test.ts.snap

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5138,7 +5138,6 @@ exports[`BridgeStatusController submitTx: Solana bridge should successfully subm
51385138
"steps": [
51395139
{
51405140
"action": "bridge",
5141-
"destAmount": "0.5",
51425141
"destAsset": {
51435142
"address": "0x...",
51445143
"assetId": "eip155:1/slip44:60",
@@ -5148,12 +5147,6 @@ exports[`BridgeStatusController submitTx: Solana bridge should successfully subm
51485147
"symbol": "ETH",
51495148
},
51505149
"destChainId": 1,
5151-
"protocol": {
5152-
"displayName": "Test Protocol",
5153-
"icon": "test-icon",
5154-
"name": "test-protocol",
5155-
},
5156-
"srcAmount": "1000000000",
51575150
"srcAsset": {
51585151
"address": "native",
51595152
"assetId": "eip155:1399811149/slip44:501",
@@ -5544,7 +5537,6 @@ exports[`BridgeStatusController submitTx: Solana swap should successfully submit
55445537
"steps": [
55455538
{
55465539
"action": "bridge",
5547-
"destAmount": "0.5",
55485540
"destAsset": {
55495541
"address": "0x...",
55505542
"assetId": "eip155:1/slip44:60",
@@ -5554,12 +5546,6 @@ exports[`BridgeStatusController submitTx: Solana swap should successfully submit
55545546
"symbol": "ETH",
55555547
},
55565548
"destChainId": 1,
5557-
"protocol": {
5558-
"displayName": "Test Protocol",
5559-
"icon": "test-icon",
5560-
"name": "test-protocol",
5561-
},
5562-
"srcAmount": "1000000000",
55635549
"srcAsset": {
55645550
"address": "native",
55655551
"assetId": "eip155:1399811149/slip44:501",
@@ -5953,7 +5939,6 @@ exports[`BridgeStatusController submitTx: Tron swap with approval should success
59535939
"steps": [
59545940
{
59555941
"action": "swap",
5956-
"destAmount": "500000000",
59575942
"destAsset": {
59585943
"address": "native",
59595944
"assetId": "tron:728126428/slip44:195",
@@ -5963,12 +5948,6 @@ exports[`BridgeStatusController submitTx: Tron swap with approval should success
59635948
"symbol": "TRX",
59645949
},
59655950
"destChainId": 728126428,
5966-
"protocol": {
5967-
"displayName": "Test Protocol",
5968-
"icon": "test-icon",
5969-
"name": "test-protocol",
5970-
},
5971-
"srcAmount": "1000000",
59725951
"srcAsset": {
59735952
"address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
59745953
"assetId": "tron:728126428/slip44:195",
@@ -6174,7 +6153,6 @@ exports[`BridgeStatusController submitTx: Tron swap with approval should success
61746153
"steps": [
61756154
{
61766155
"action": "swap",
6177-
"destAmount": "500000000",
61786156
"destAsset": {
61796157
"address": "native",
61806158
"assetId": "tron:728126428/slip44:195",
@@ -6184,12 +6162,6 @@ exports[`BridgeStatusController submitTx: Tron swap with approval should success
61846162
"symbol": "TRX",
61856163
},
61866164
"destChainId": 728126428,
6187-
"protocol": {
6188-
"displayName": "Test Protocol",
6189-
"icon": "test-icon",
6190-
"name": "test-protocol",
6191-
},
6192-
"srcAmount": "1000000",
61936165
"srcAsset": {
61946166
"address": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
61956167
"assetId": "tron:728126428/slip44:195",

0 commit comments

Comments
 (0)