-
-
Notifications
You must be signed in to change notification settings - Fork 262
feat: intent-based swaps support #6547
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
packages/bridge-status-controller/src/bridge-status-controller.ts
Outdated
Show resolved
Hide resolved
packages/bridge-status-controller/src/bridge-status-controller.ts
Outdated
Show resolved
Hide resolved
4832227 to
126f733
Compare
packages/transaction-controller/src/helpers/PendingTransactionTracker.ts
Outdated
Show resolved
Hide resolved
packages/bridge-status-controller/src/bridge-status-controller.ts
Outdated
Show resolved
Hide resolved
|
Given the volume of code here, I'd recommend merging the bridge controllers code in isolation, then we can address any required changes to the |
## 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/contributing.md#updating-changelogs) - [ ] 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] > - **Keyring Controller**: New `KeyringControllerError` class with codes/context, JSON/string serialization, and error chaining; refactors controller to throw `KeyringControllerError` (renamed enum to `KeyringControllerErrorMessage`); exports `errors`; extensive test updates including hardware wallet error preservation. > - **Multichain Account Service (Snaps)**: Add `SnapPlatformWatcher` and `MultichainAccountService:ensureCanUseSnapPlatform`; new `SnapAccountProvider.withSnap` guard (and make `client` private); update `Sol/Btc/Trx` providers to use guarded `client/keyring` access for discovery/creation; add lodash; new tests. > - **Bridge/Intents**: In bridge status controller, set `isStateOnly: true` on intent addTransaction and remove `swaps` metadata and initial gas estimate. > - **Assets/Bridge package bumps**: `@metamask/assets-controllers` to `95.0.0` with changelog links; `bridge-controller` depends on it; monorepo version to `742.0.0`. > > Scope: error-handling overhaul and Snap readiness guard across providers; minor intent/bridge metadata change; package version bumps. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit e493417. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Monte Lai <[email protected]> Co-authored-by: Charly Chevalier <[email protected]> Co-authored-by: Salim TOUBAL <[email protected]> Co-authored-by: Matthew Walsh <[email protected]>
| return TransactionStatus.confirmed; | ||
| case IntentOrderStatus.FAILED: | ||
| case IntentOrderStatus.EXPIRED: | ||
| return TransactionStatus.failed; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cancelled intent orders incorrectly mapped to submitted status
Medium Severity
The mapIntentOrderStatusToTransactionStatus function is missing a case for IntentOrderStatus.CANCELLED, causing it to fall through to the default and return TransactionStatus.submitted. However, in #updateBridgeHistoryFromIntentOrder, CANCELLED is correctly included in the isFailed array and mapped to StatusTypes.FAILED. This inconsistency means cancelled orders will show as "submitted" in the TransactionController but "failed" in the bridge history, creating a confusing user experience where the same order appears in different states across the UI.
Additional Locations (1)
| // Check metadata for additional transaction hashes | ||
| const metadataTxHashes = Array.isArray(intentOrder.metadata.txHashes) | ||
| ? intentOrder.metadata.txHashes | ||
| : []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String txHashes ignored when not array format
Medium Severity
The IntentOrder type and schema explicitly allow metadata.txHashes to be either string[] or string, but the code only handles the array case. When txHashes is a single string, Array.isArray() returns false and metadataTxHashes becomes an empty array, silently discarding the transaction hash. If intentOrder.txHash is also undefined, this results in lost transaction hash data that won't be recorded in the history.
| return TransactionStatus.confirmed; | ||
| case IntentOrderStatus.FAILED: | ||
| case IntentOrderStatus.EXPIRED: | ||
| return TransactionStatus.failed; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cancelled intent orders mapped to wrong transaction status
Medium Severity
The mapIntentOrderStatusToTransactionStatus function is missing a case for IntentOrderStatus.CANCELLED. When an intent order is cancelled, it falls through to the default case and incorrectly returns TransactionStatus.submitted. This is inconsistent with #updateBridgeHistoryFromIntentOrder which correctly treats CANCELLED as a failed state. The result is that the bridge history shows the order as failed, but the TransactionController transaction shows it as submitted, causing conflicting UI states.
Additional Locations (1)
| // Check metadata for additional transaction hashes | ||
| const metadataTxHashes = Array.isArray(intentOrder.metadata.txHashes) | ||
| ? intentOrder.metadata.txHashes | ||
| : []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String value in metadata.txHashes silently discarded
Medium Severity
The IntentOrder type defines metadata.txHashes as string[] | string, but the code at #updateBridgeHistoryFromIntentOrder only handles the array case. When the API returns a single string instead of an array, Array.isArray() returns false and the code falls back to an empty array, losing the transaction hash. This could cause transaction hashes to be missing from the history when the API returns txHashes as a single string value.
| * This is called during initialization | ||
| */ | ||
| readonly #restartPollingForIncompleteHistoryItems = () => { | ||
| readonly #restartPollingForIncompleteHistoryItems = (): void => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Intent transactions excluded from polling restart on browser reopen
High Severity
The #restartPollingForIncompleteHistoryItems method has two gaps that prevent intent-based transactions from resuming polling after browser restart. First, the status filter (lines 404-408) only checks for PENDING and UNKNOWN, but excludes the new StatusTypes.SUBMITTED status used by intent orders. Second, the filter at lines 415-422 only passes cross-chain bridge transactions, excluding same-chain intent swaps entirely. However, #startPollingForTxId correctly handles intent transactions via txId.startsWith('intent:'). This causes intent-based swaps to become stuck with no status updates if the user closes and reopens their browser while a swap is in progress.
References
Relates to https://consensyssoftware.atlassian.net/browse/BETR-5
Checklist
Note
Introduces intent-based swap/bridge flow end-to-end.
Intent/IntentOrderschemas and optionalquote.intent; extendStatusTypeswithSUBMITTEDsubmitIntentaction; create synthetic TC tx, write history (originalTransactionId,srcTxHashes), and poll intent order status via newIntentApiImpl; map intent statuses to bridge/TC statuses; start/stop polling and track events (skip whenfeatureId)IntentApiImplwithsubmitIntent/getOrderStatusand status mappingWritten by Cursor Bugbot for commit 87e2d3a. This will update automatically on new commits. Configure here.