Skip to content

feat: fetch batched swap quotes#8711

Merged
micaelae merged 13 commits into
mainfrom
swaps4443-batch-quotes
May 7, 2026
Merged

feat: fetch batched swap quotes#8711
micaelae merged 13 commits into
mainfrom
swaps4443-batch-quotes

Conversation

@micaelae
Copy link
Copy Markdown
Member

@micaelae micaelae commented May 6, 2026

Explanation

This PR implements quote polling for batched swap requests

Changes

  • updateBridgeQuoteRequest now takes 2 extra params: the quote request’s index and the total quoteRequestCount within the batch. no changes in how we are using this handler for regular swaps
  • the new selectBatchSellQuotes selector returns the recommended quote for each quoteRequest, and aggregated amounts for display purposes
  • isValidBatchSellQuoteRequest

Usage

  • the clients will need to maintain a list of requests, each one identified by an index. the index identifies the quoteRequest and its related side effects (quotes, metrics, submission etc) once it’s passed to updateBridgeQuoteRequest
  • to access quotes for a single quoteRequest, use the same index used during quoteRequest update

Minimal client examples

References

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

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
This is a breaking API/state-shape change (quoteRequest becomes an array) that touches quote polling/streaming, analytics properties, and exchange-rate lookup logic; regressions could affect quote fetching and refresh behavior across swaps/bridges.

Overview
Adds BatchSell (batched swap) quote support by changing quoteRequest state and polling inputs from a single request to an array, allowing callers to update a specific request via new updateBridgeQuoteRequestParams(…, quoteRequestIndex, quoteRequestCount) parameters.

Quote fetching/streaming is updated to accept multiple requests: SSE uses a new POST /getBatchQuoteStream path when batching, tags incoming quotes with quoteRequestIndex, traces via new Sentry trace name Batch Sell Quotes Fetched, and adjusts polling stop/refresh logic to continue as long as any request is sufficiently funded.

Selectors and rate lookup are extended for batching: adds selectBatchSellQuotes (per-request recommended quotes plus aggregated received/fee totals), switches exchange-rate selection to selectExchangeRateByAssetId, and exports isValidBatchSellQuoteRequest; tests/snapshots are updated and a new SSE batch test is added.

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

@micaelae micaelae marked this pull request as ready for review May 6, 2026 20:16
@micaelae micaelae requested review from a team as code owners May 6, 2026 20:16
Comment thread packages/bridge-controller/src/bridge-controller.ts
@micaelae micaelae enabled auto-merge May 6, 2026 20:20
@micaelae
Copy link
Copy Markdown
Member Author

micaelae commented May 6, 2026

@metamaskbot publish-preview

Comment thread packages/bridge-controller/src/selectors.ts Outdated
Comment thread packages/bridge-controller/src/selectors.test.ts Outdated
Comment thread packages/bridge-controller/src/bridge-controller.ts
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.3.0-preview-f90b07931
@metamask-previews/accounts-controller@38.0.0-preview-f90b07931
@metamask-previews/address-book-controller@7.1.1-preview-f90b07931
@metamask-previews/ai-controllers@0.6.3-preview-f90b07931
@metamask-previews/analytics-controller@1.0.1-preview-f90b07931
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-f90b07931
@metamask-previews/announcement-controller@8.1.0-preview-f90b07931
@metamask-previews/app-metadata-controller@2.0.1-preview-f90b07931
@metamask-previews/approval-controller@9.0.1-preview-f90b07931
@metamask-previews/assets-controller@6.4.0-preview-f90b07931
@metamask-previews/assets-controllers@106.0.0-preview-f90b07931
@metamask-previews/authenticated-user-storage@1.0.0-preview-f90b07931
@metamask-previews/base-controller@9.1.0-preview-f90b07931
@metamask-previews/base-data-service@0.1.1-preview-f90b07931
@metamask-previews/bridge-controller@71.1.1-preview-f90b07931
@metamask-previews/bridge-status-controller@71.1.0-preview-f90b07931
@metamask-previews/build-utils@3.0.4-preview-f90b07931
@metamask-previews/chain-agnostic-permission@1.5.0-preview-f90b07931
@metamask-previews/chomp-api-service@3.0.0-preview-f90b07931
@metamask-previews/claims-controller@0.5.0-preview-f90b07931
@metamask-previews/client-controller@1.0.1-preview-f90b07931
@metamask-previews/compliance-controller@2.0.0-preview-f90b07931
@metamask-previews/composable-controller@12.0.1-preview-f90b07931
@metamask-previews/config-registry-controller@0.3.0-preview-f90b07931
@metamask-previews/connectivity-controller@0.2.0-preview-f90b07931
@metamask-previews/controller-utils@11.20.0-preview-f90b07931
@metamask-previews/core-backend@6.2.1-preview-f90b07931
@metamask-previews/delegation-controller@3.0.0-preview-f90b07931
@metamask-previews/earn-controller@12.1.0-preview-f90b07931
@metamask-previews/eip-5792-middleware@3.0.3-preview-f90b07931
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.0-preview-f90b07931
@metamask-previews/eip1193-permission-middleware@2.0.0-preview-f90b07931
@metamask-previews/ens-controller@19.1.1-preview-f90b07931
@metamask-previews/eth-block-tracker@15.0.1-preview-f90b07931
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-f90b07931
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-f90b07931
@metamask-previews/foundryup@1.0.1-preview-f90b07931
@metamask-previews/gas-fee-controller@26.2.0-preview-f90b07931
@metamask-previews/gator-permissions-controller@4.1.0-preview-f90b07931
@metamask-previews/geolocation-controller@0.1.2-preview-f90b07931
@metamask-previews/json-rpc-engine@10.3.0-preview-f90b07931
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-f90b07931
@metamask-previews/keyring-controller@25.5.0-preview-f90b07931
@metamask-previews/logging-controller@8.0.1-preview-f90b07931
@metamask-previews/message-manager@14.1.1-preview-f90b07931
@metamask-previews/messenger@1.2.0-preview-f90b07931
@metamask-previews/messenger-cli@0.2.0-preview-f90b07931
@metamask-previews/money-account-balance-service@0.2.0-preview-f90b07931
@metamask-previews/money-account-controller@0.3.0-preview-f90b07931
@metamask-previews/money-account-upgrade-controller@1.3.1-preview-f90b07931
@metamask-previews/multichain-account-service@9.0.0-preview-f90b07931
@metamask-previews/multichain-api-middleware@3.0.0-preview-f90b07931
@metamask-previews/multichain-network-controller@3.1.0-preview-f90b07931
@metamask-previews/multichain-transactions-controller@7.1.0-preview-f90b07931
@metamask-previews/name-controller@9.1.1-preview-f90b07931
@metamask-previews/network-controller@30.1.0-preview-f90b07931
@metamask-previews/network-enablement-controller@5.1.0-preview-f90b07931
@metamask-previews/notification-services-controller@23.1.0-preview-f90b07931
@metamask-previews/passkey-controller@2.0.1-preview-f90b07931
@metamask-previews/permission-controller@13.1.0-preview-f90b07931
@metamask-previews/permission-log-controller@5.1.0-preview-f90b07931
@metamask-previews/perps-controller@6.0.0-preview-f90b07931
@metamask-previews/phishing-controller@17.1.1-preview-f90b07931
@metamask-previews/polling-controller@16.0.4-preview-f90b07931
@metamask-previews/preferences-controller@23.1.0-preview-f90b07931
@metamask-previews/profile-metrics-controller@3.1.3-preview-f90b07931
@metamask-previews/profile-sync-controller@28.0.2-preview-f90b07931
@metamask-previews/ramps-controller@13.3.0-preview-f90b07931
@metamask-previews/rate-limit-controller@7.0.1-preview-f90b07931
@metamask-previews/react-data-query@0.2.0-preview-f90b07931
@metamask-previews/remote-feature-flag-controller@4.2.0-preview-f90b07931
@metamask-previews/sample-controllers@4.0.4-preview-f90b07931
@metamask-previews/seedless-onboarding-controller@9.1.0-preview-f90b07931
@metamask-previews/selected-network-controller@26.1.1-preview-f90b07931
@metamask-previews/shield-controller@5.1.1-preview-f90b07931
@metamask-previews/signature-controller@39.2.0-preview-f90b07931
@metamask-previews/snap-account-service@0.0.0-preview-f90b07931
@metamask-previews/social-controllers@2.2.0-preview-f90b07931
@metamask-previews/storage-service@1.0.1-preview-f90b07931
@metamask-previews/subscription-controller@6.1.2-preview-f90b07931
@metamask-previews/transaction-controller@65.2.0-preview-f90b07931
@metamask-previews/transaction-pay-controller@21.1.0-preview-f90b07931
@metamask-previews/user-operation-controller@41.2.0-preview-f90b07931

srcAsset: { address: srcTokenAddress, chainId: srcChainId },
destAsset: { address: destTokenAddress, chainId: destChainId },
}: QuoteResponse['quote']): string => {
return `${formatAddressToAssetId(srcTokenAddress, srcChainId)}-${formatAddressToAssetId(destTokenAddress, destChainId)}`.toLowerCase();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we need to worry that non-EVM addresses can be case sensitive here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good callout! removed the lowercasing

Comment thread packages/bridge-controller/src/utils/fetch.ts Outdated
export type BridgeControllerState = {
quoteRequest: Partial<GenericQuoteRequest>;
quoteRequest: Partial<GenericQuoteRequest>[];
quotes: (QuoteResponse & L1GasFees & NonEvmFees)[];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Interesting, so quotes is still a single dimensional array? For batch quote requests does each request get single or multiple quotes?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yea the backend returns a stream of all of them, which we match up with the quoteRequest as they arrive. There can be multiple quotes for each request but the batch selector only returns the best one for each

Comment thread packages/bridge-controller/src/bridge-controller.ts
Comment thread packages/bridge-controller/src/bridge-controller.ts
@micaelae micaelae disabled auto-merge May 6, 2026 23:12
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 1 potential issue.

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 c5cc1aa. Configure here.

Comment thread packages/bridge-controller/src/bridge-controller.ts
@micaelae micaelae enabled auto-merge May 6, 2026 23:45
@micaelae
Copy link
Copy Markdown
Member Author

micaelae commented May 6, 2026

@metamaskbot publish-preview

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.3.0-preview-9e2a7fac5
@metamask-previews/accounts-controller@38.0.0-preview-9e2a7fac5
@metamask-previews/address-book-controller@7.1.1-preview-9e2a7fac5
@metamask-previews/ai-controllers@0.6.3-preview-9e2a7fac5
@metamask-previews/analytics-controller@1.0.1-preview-9e2a7fac5
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-9e2a7fac5
@metamask-previews/announcement-controller@8.1.0-preview-9e2a7fac5
@metamask-previews/app-metadata-controller@2.0.1-preview-9e2a7fac5
@metamask-previews/approval-controller@9.0.1-preview-9e2a7fac5
@metamask-previews/assets-controller@6.4.0-preview-9e2a7fac5
@metamask-previews/assets-controllers@106.0.0-preview-9e2a7fac5
@metamask-previews/authenticated-user-storage@1.0.0-preview-9e2a7fac5
@metamask-previews/base-controller@9.1.0-preview-9e2a7fac5
@metamask-previews/base-data-service@0.1.1-preview-9e2a7fac5
@metamask-previews/bridge-controller@71.1.1-preview-9e2a7fac5
@metamask-previews/bridge-status-controller@71.1.0-preview-9e2a7fac5
@metamask-previews/build-utils@3.0.4-preview-9e2a7fac5
@metamask-previews/chain-agnostic-permission@1.5.0-preview-9e2a7fac5
@metamask-previews/chomp-api-service@3.0.0-preview-9e2a7fac5
@metamask-previews/claims-controller@0.5.0-preview-9e2a7fac5
@metamask-previews/client-controller@1.0.1-preview-9e2a7fac5
@metamask-previews/compliance-controller@2.0.0-preview-9e2a7fac5
@metamask-previews/composable-controller@12.0.1-preview-9e2a7fac5
@metamask-previews/config-registry-controller@0.3.0-preview-9e2a7fac5
@metamask-previews/connectivity-controller@0.2.0-preview-9e2a7fac5
@metamask-previews/controller-utils@11.20.0-preview-9e2a7fac5
@metamask-previews/core-backend@6.2.1-preview-9e2a7fac5
@metamask-previews/delegation-controller@3.0.0-preview-9e2a7fac5
@metamask-previews/earn-controller@12.1.0-preview-9e2a7fac5
@metamask-previews/eip-5792-middleware@3.0.3-preview-9e2a7fac5
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.0-preview-9e2a7fac5
@metamask-previews/eip1193-permission-middleware@2.0.0-preview-9e2a7fac5
@metamask-previews/ens-controller@19.1.1-preview-9e2a7fac5
@metamask-previews/eth-block-tracker@15.0.1-preview-9e2a7fac5
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-9e2a7fac5
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-9e2a7fac5
@metamask-previews/foundryup@1.0.1-preview-9e2a7fac5
@metamask-previews/gas-fee-controller@26.2.0-preview-9e2a7fac5
@metamask-previews/gator-permissions-controller@4.1.0-preview-9e2a7fac5
@metamask-previews/geolocation-controller@0.1.2-preview-9e2a7fac5
@metamask-previews/json-rpc-engine@10.3.0-preview-9e2a7fac5
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-9e2a7fac5
@metamask-previews/keyring-controller@25.5.0-preview-9e2a7fac5
@metamask-previews/logging-controller@8.0.1-preview-9e2a7fac5
@metamask-previews/message-manager@14.1.1-preview-9e2a7fac5
@metamask-previews/messenger@1.2.0-preview-9e2a7fac5
@metamask-previews/messenger-cli@0.2.0-preview-9e2a7fac5
@metamask-previews/money-account-balance-service@0.2.0-preview-9e2a7fac5
@metamask-previews/money-account-controller@0.3.0-preview-9e2a7fac5
@metamask-previews/money-account-upgrade-controller@1.3.1-preview-9e2a7fac5
@metamask-previews/multichain-account-service@9.0.0-preview-9e2a7fac5
@metamask-previews/multichain-api-middleware@3.0.0-preview-9e2a7fac5
@metamask-previews/multichain-network-controller@3.1.0-preview-9e2a7fac5
@metamask-previews/multichain-transactions-controller@7.1.0-preview-9e2a7fac5
@metamask-previews/name-controller@9.1.1-preview-9e2a7fac5
@metamask-previews/network-controller@30.1.0-preview-9e2a7fac5
@metamask-previews/network-enablement-controller@5.1.0-preview-9e2a7fac5
@metamask-previews/notification-services-controller@23.1.0-preview-9e2a7fac5
@metamask-previews/passkey-controller@2.0.1-preview-9e2a7fac5
@metamask-previews/permission-controller@13.1.0-preview-9e2a7fac5
@metamask-previews/permission-log-controller@5.1.0-preview-9e2a7fac5
@metamask-previews/perps-controller@6.0.0-preview-9e2a7fac5
@metamask-previews/phishing-controller@17.1.1-preview-9e2a7fac5
@metamask-previews/polling-controller@16.0.4-preview-9e2a7fac5
@metamask-previews/preferences-controller@23.1.0-preview-9e2a7fac5
@metamask-previews/profile-metrics-controller@3.1.3-preview-9e2a7fac5
@metamask-previews/profile-sync-controller@28.0.2-preview-9e2a7fac5
@metamask-previews/ramps-controller@13.3.0-preview-9e2a7fac5
@metamask-previews/rate-limit-controller@7.0.1-preview-9e2a7fac5
@metamask-previews/react-data-query@0.2.0-preview-9e2a7fac5
@metamask-previews/remote-feature-flag-controller@4.2.0-preview-9e2a7fac5
@metamask-previews/sample-controllers@4.0.4-preview-9e2a7fac5
@metamask-previews/seedless-onboarding-controller@9.1.0-preview-9e2a7fac5
@metamask-previews/selected-network-controller@26.1.1-preview-9e2a7fac5
@metamask-previews/shield-controller@5.1.1-preview-9e2a7fac5
@metamask-previews/signature-controller@39.2.0-preview-9e2a7fac5
@metamask-previews/snap-account-service@0.0.0-preview-9e2a7fac5
@metamask-previews/social-controllers@2.2.0-preview-9e2a7fac5
@metamask-previews/storage-service@1.0.1-preview-9e2a7fac5
@metamask-previews/subscription-controller@6.1.2-preview-9e2a7fac5
@metamask-previews/transaction-controller@65.2.0-preview-9e2a7fac5
@metamask-previews/transaction-pay-controller@21.1.0-preview-9e2a7fac5
@metamask-previews/user-operation-controller@41.2.0-preview-9e2a7fac5

@micaelae micaelae added this pull request to the merge queue May 7, 2026
Merged via the queue into main with commit ec46875 May 7, 2026
366 checks passed
@micaelae micaelae deleted the swaps4443-batch-quotes branch May 7, 2026 14:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants