@metamask/bridge-status-controller 70.0.1 → 70.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [70.0.3]
11
+
12
+ ### Changed
13
+
14
+ - Bump `@metamask/snaps-controllers` from `^17.2.0` to `^19.0.0` ([#8319](https://github.com/MetaMask/core/pull/8319))
15
+ - Bump `@metamask/accounts-controller` from `^37.1.0` to `^37.1.1` ([#8325](https://github.com/MetaMask/core/pull/8325))
16
+ - Bump `@metamask/bridge-controller` from `^69.2.2` to `^69.2.3` ([#8325](https://github.com/MetaMask/core/pull/8325))
17
+ - Bump `@metamask/profile-sync-controller` from `^28.0.1` to `^28.0.2` ([#8325](https://github.com/MetaMask/core/pull/8325))
18
+
19
+ ## [70.0.2]
20
+
21
+ ### Changed
22
+
23
+ - Bump `@metamask/accounts-controller` from `^37.0.0` to `^37.1.0` ([#8317](https://github.com/MetaMask/core/pull/8317))
24
+ - Bump `@metamask/base-controller` from `^9.0.0` to `^9.0.1` ([#8317](https://github.com/MetaMask/core/pull/8317))
25
+ - Bump `@metamask/bridge-controller` from `^69.2.1` to `^69.2.2` ([#8317](https://github.com/MetaMask/core/pull/8317))
26
+ - Bump `@metamask/gas-fee-controller` from `^26.1.0` to `^26.1.1` ([#8317](https://github.com/MetaMask/core/pull/8317))
27
+ - Bump `@metamask/keyring-controller` from `^25.1.0` to `^25.1.1` ([#8317](https://github.com/MetaMask/core/pull/8317))
28
+ - Bump `@metamask/network-controller` from `^30.0.0` to `^30.0.1` ([#8317](https://github.com/MetaMask/core/pull/8317))
29
+ - Bump `@metamask/polling-controller` from `^16.0.3` to `^16.0.4` ([#8317](https://github.com/MetaMask/core/pull/8317))
30
+ - Bump `@metamask/profile-sync-controller` from `^28.0.0` to `^28.0.1` ([#8317](https://github.com/MetaMask/core/pull/8317))
31
+ - Bump `@metamask/transaction-controller` from `^63.1.0` to `^63.3.1` ([#8301](https://github.com/MetaMask/core/pull/8301), [#8313](https://github.com/MetaMask/core/pull/8313), [#8317](https://github.com/MetaMask/core/pull/8317))
32
+
10
33
  ## [70.0.1]
11
34
 
12
35
  ### Changed
@@ -16,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
39
 
17
40
  ### Fixed
18
41
 
42
+ - Publish UnifiedSwapBridge Failed event for any exception thrown during `submitTx`. Previously the Failed event was only getting published for EVM txs after tx submission ([#8277](https://github.com/MetaMask/core/pull/8277))
19
43
  - Keep EIP-7702 batching disabled for gasless transactions that use smart transactions / `eth_sendBundle` when the quote is gas-included but not gas-included-7702 even when the account is a smart account ([#8275](https://github.com/MetaMask/core/pull/8275))
20
44
  - For hardware wallets on MetaMask Mobile, non-batch EVM flows with ERC-20 approval now run the hardware-wallet delay before waiting for approval confirmation, preserving Ledger second-prompt spacing while gas estimation still runs after allowance is set on-chain ([#8268](https://github.com/MetaMask/core/pull/8268))
21
45
 
@@ -1059,7 +1083,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1059
1083
 
1060
1084
  - Initial release ([#5317](https://github.com/MetaMask/core/pull/5317))
1061
1085
 
1062
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@70.0.1...HEAD
1086
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@70.0.3...HEAD
1087
+ [70.0.3]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@70.0.2...@metamask/bridge-status-controller@70.0.3
1088
+ [70.0.2]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@70.0.1...@metamask/bridge-status-controller@70.0.2
1063
1089
  [70.0.1]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@70.0.0...@metamask/bridge-status-controller@70.0.1
1064
1090
  [70.0.0]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@69.0.0...@metamask/bridge-status-controller@70.0.0
1065
1091
  [69.0.0]: https://github.com/MetaMask/core/compare/@metamask/bridge-status-controller@68.1.0...@metamask/bridge-status-controller@69.0.0
@@ -519,140 +519,131 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
519
519
  }
520
520
  const isHardwareAccount = (0, bridge_controller_1.isHardwareWallet)(selectedAccount);
521
521
  const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, isStxEnabledOnClient, isHardwareAccount, location, abTests, activeAbTests);
522
- // Emit Submitted event after submit button is clicked
523
- !quoteResponse.featureId &&
524
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Submitted, undefined, preConfirmationProperties);
525
522
  let txMeta;
526
523
  let approvalTxId;
527
524
  let isDelegatedAccount = false;
528
525
  const startTime = Date.now();
529
526
  const isBridgeTx = (0, bridge_controller_1.isCrossChain)(quoteResponse.quote.srcChainId, quoteResponse.quote.destChainId);
530
527
  const isTronTx = (0, bridge_controller_1.isTronChainId)(quoteResponse.quote.srcChainId);
531
- // Submit non-EVM tx (Solana, BTC, Tron)
532
- if ((0, bridge_controller_1.isNonEvmChainId)(quoteResponse.quote.srcChainId)) {
533
- // Handle non-EVM approval if present (e.g., Tron token approvals)
534
- if (quoteResponse.approval && (0, bridge_controller_1.isTronTrade)(quoteResponse.approval)) {
535
- const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, (0, trace_1.getApprovalTraceParams)(quoteResponse, false), async () => {
536
- try {
528
+ try {
529
+ // Emit Submitted event after submit button is clicked
530
+ !quoteResponse.featureId &&
531
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Submitted, undefined, preConfirmationProperties);
532
+ // Submit non-EVM tx (Solana, BTC, Tron)
533
+ if ((0, bridge_controller_1.isNonEvmChainId)(quoteResponse.quote.srcChainId)) {
534
+ // Handle non-EVM approval if present (e.g., Tron token approvals)
535
+ if (quoteResponse.approval && (0, bridge_controller_1.isTronTrade)(quoteResponse.approval)) {
536
+ const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, (0, trace_1.getApprovalTraceParams)(quoteResponse, false), async () => {
537
537
  return quoteResponse.approval &&
538
538
  (0, bridge_controller_1.isTronTrade)(quoteResponse.approval)
539
539
  ? await (0, snaps_1.handleNonEvmTx)(this.messenger, quoteResponse.approval, quoteResponse, selectedAccount)
540
540
  : /* c8 ignore start */
541
541
  undefined;
542
542
  /* c8 ignore end */
543
- }
544
- catch (error) {
545
- !quoteResponse.featureId &&
546
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Failed, undefined, {
547
- error_message: error?.message,
548
- ...preConfirmationProperties,
549
- });
550
- throw error;
551
- }
552
- });
553
- approvalTxId = approvalTxMeta?.id;
554
- // Add delay after approval similar to EVM flow
555
- await (0, transaction_1.handleApprovalDelay)(quoteResponse.quote.srcChainId);
556
- }
557
- txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, (0, trace_1.getTraceParams)(quoteResponse, false), async () => {
558
- try {
543
+ });
544
+ approvalTxId = approvalTxMeta?.id;
545
+ // Add delay after approval similar to EVM flow
546
+ await (0, transaction_1.handleApprovalDelay)(quoteResponse.quote.srcChainId);
547
+ }
548
+ txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, (0, trace_1.getTraceParams)(quoteResponse, false), async () => {
559
549
  if (!((0, bridge_controller_1.isTronTrade)(quoteResponse.trade) ||
560
550
  (0, bridge_controller_1.isBitcoinTrade)(quoteResponse.trade) ||
561
551
  typeof quoteResponse.trade === 'string')) {
562
552
  throw new Error('Failed to submit cross-chain swap transaction: trade is not a non-EVM transaction');
563
553
  }
564
554
  return await (0, snaps_1.handleNonEvmTx)(this.messenger, quoteResponse.trade, quoteResponse, selectedAccount);
565
- }
566
- catch (error) {
567
- !quoteResponse.featureId &&
568
- __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Failed, undefined, {
569
- error_message: error?.message,
570
- ...preConfirmationProperties,
555
+ });
556
+ }
557
+ else {
558
+ // Submit EVM tx
559
+ // For hardware wallets on Mobile, this is fixes an issue where the Ledger does not get prompted for the 2nd approval
560
+ // Extension does not have this issue
561
+ const requireApproval = __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === types_1.BridgeClientId.MOBILE && isHardwareAccount;
562
+ // Handle smart transactions if enabled
563
+ txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, (0, trace_1.getTraceParams)(quoteResponse, isStxEnabledOnClient), async () => {
564
+ if (!(0, bridge_controller_1.isEvmTxData)(quoteResponse.trade)) {
565
+ throw new Error('Failed to submit cross-chain swap transaction: trade is not an EVM transaction');
566
+ }
567
+ // Check if the account is an EIP-7702 delegated account
568
+ // Delegated accounts only allow 1 in-flight tx, so approve + swap
569
+ // must be batched into a single transaction
570
+ const hexChainId = (0, bridge_controller_1.formatChainIdToHex)(quoteResponse.quote.srcChainId);
571
+ isDelegatedAccount = await (0, transaction_1.checkIsDelegatedAccount)(this.messenger, quoteResponse.trade.from, [hexChainId]);
572
+ if (isStxEnabledOnClient ||
573
+ quoteResponse.quote.gasIncluded7702 ||
574
+ isDelegatedAccount) {
575
+ const { tradeMeta, approvalMeta } = await __classPrivateFieldGet(this, _BridgeStatusController_handleEvmTransactionBatch, "f").call(this, {
576
+ isBridgeTx,
577
+ resetApproval: quoteResponse.resetApproval,
578
+ approval: quoteResponse.approval &&
579
+ (0, bridge_controller_1.isEvmTxData)(quoteResponse.approval)
580
+ ? quoteResponse.approval
581
+ : undefined,
582
+ trade: quoteResponse.trade,
583
+ quoteResponse,
584
+ requireApproval,
585
+ isDelegatedAccount,
571
586
  });
572
- throw error;
573
- }
574
- });
575
- }
576
- else {
577
- // Submit EVM tx
578
- // For hardware wallets on Mobile, this is fixes an issue where the Ledger does not get prompted for the 2nd approval
579
- // Extension does not have this issue
580
- const requireApproval = __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === types_1.BridgeClientId.MOBILE && isHardwareAccount;
581
- // Handle smart transactions if enabled
582
- txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, (0, trace_1.getTraceParams)(quoteResponse, isStxEnabledOnClient), async () => {
583
- if (!(0, bridge_controller_1.isEvmTxData)(quoteResponse.trade)) {
584
- throw new Error('Failed to submit cross-chain swap transaction: trade is not an EVM transaction');
585
- }
586
- // Check if the account is an EIP-7702 delegated account
587
- // Delegated accounts only allow 1 in-flight tx, so approve + swap
588
- // must be batched into a single transaction
589
- const hexChainId = (0, bridge_controller_1.formatChainIdToHex)(quoteResponse.quote.srcChainId);
590
- isDelegatedAccount = await (0, transaction_1.checkIsDelegatedAccount)(this.messenger, quoteResponse.trade.from, [hexChainId]);
591
- if (isStxEnabledOnClient ||
592
- quoteResponse.quote.gasIncluded7702 ||
593
- isDelegatedAccount) {
594
- const { tradeMeta, approvalMeta } = await __classPrivateFieldGet(this, _BridgeStatusController_handleEvmTransactionBatch, "f").call(this, {
595
- isBridgeTx,
596
- resetApproval: quoteResponse.resetApproval,
597
- approval: quoteResponse.approval && (0, bridge_controller_1.isEvmTxData)(quoteResponse.approval)
598
- ? quoteResponse.approval
599
- : undefined,
600
- trade: quoteResponse.trade,
587
+ approvalTxId = approvalMeta?.id;
588
+ return tradeMeta;
589
+ }
590
+ // Set approval time and id if an approval tx is needed
591
+ const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleApprovalTx, "f").call(this, quoteResponse, isBridgeTx, quoteResponse.quote.srcChainId, quoteResponse.approval && (0, bridge_controller_1.isEvmTxData)(quoteResponse.approval)
592
+ ? quoteResponse.approval
593
+ : undefined, quoteResponse.resetApproval, requireApproval);
594
+ approvalTxId = approvalTxMeta?.id;
595
+ // Hardware-wallet delay first (Ledger second-prompt spacing), then wait for
596
+ // on-chain approval confirmation so swap gas estimation runs after allowance is set.
597
+ if (requireApproval && approvalTxMeta) {
598
+ await (0, transaction_1.handleMobileHardwareWalletDelay)(requireApproval);
599
+ await (0, transaction_1.waitForTxConfirmation)(this.messenger, approvalTxMeta.id);
600
+ }
601
+ else {
602
+ await (0, transaction_1.handleMobileHardwareWalletDelay)(requireApproval);
603
+ }
604
+ // Generate actionId for pre-submission history (non-batch EVM only)
605
+ const actionId = (0, transaction_1.generateActionId)().toString();
606
+ // Add pre-submission history keyed by actionId
607
+ // This ensures we have quote data available if transaction fails during submission
608
+ __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
609
+ accountAddress: selectedAccount.address,
601
610
  quoteResponse,
611
+ slippagePercentage: 0,
612
+ isStxEnabled: isStxEnabledOnClient,
613
+ startTime,
614
+ approvalTxId,
615
+ location,
616
+ abTests,
617
+ activeAbTests,
618
+ actionId,
619
+ });
620
+ // Pass txFee when gasIncluded is true to use the quote's gas fees
621
+ // instead of re-estimating (which would fail for max native token swaps)
622
+ const tradeTxMeta = await (0, transaction_1.submitEvmTransaction)({
623
+ messenger: this.messenger,
624
+ transactionType: isBridgeTx
625
+ ? transaction_controller_1.TransactionType.bridge
626
+ : transaction_controller_1.TransactionType.swap,
627
+ trade: quoteResponse.trade,
602
628
  requireApproval,
603
- isDelegatedAccount,
629
+ txFee: quoteResponse.quote.gasIncluded
630
+ ? quoteResponse.quote.feeData.txFee
631
+ : undefined,
632
+ actionId,
604
633
  });
605
- approvalTxId = approvalMeta?.id;
606
- return tradeMeta;
607
- }
608
- // Set approval time and id if an approval tx is needed
609
- const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleApprovalTx, "f").call(this, quoteResponse, isBridgeTx, quoteResponse.quote.srcChainId, quoteResponse.approval && (0, bridge_controller_1.isEvmTxData)(quoteResponse.approval)
610
- ? quoteResponse.approval
611
- : undefined, quoteResponse.resetApproval, requireApproval);
612
- approvalTxId = approvalTxMeta?.id;
613
- // Hardware-wallet delay first (Ledger second-prompt spacing), then wait for
614
- // on-chain approval confirmation so swap gas estimation runs after allowance is set.
615
- if (requireApproval && approvalTxMeta) {
616
- await (0, transaction_1.handleMobileHardwareWalletDelay)(requireApproval);
617
- await (0, transaction_1.waitForTxConfirmation)(this.messenger, approvalTxMeta.id);
618
- }
619
- else {
620
- await (0, transaction_1.handleMobileHardwareWalletDelay)(requireApproval);
621
- }
622
- // Generate actionId for pre-submission history (non-batch EVM only)
623
- const actionId = (0, transaction_1.generateActionId)().toString();
624
- // Add pre-submission history keyed by actionId
625
- // This ensures we have quote data available if transaction fails during submission
626
- __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
627
- accountAddress: selectedAccount.address,
628
- quoteResponse,
629
- slippagePercentage: 0,
630
- isStxEnabled: isStxEnabledOnClient,
631
- startTime,
632
- approvalTxId,
633
- location,
634
- abTests,
635
- activeAbTests,
636
- actionId,
634
+ // On success, rekey from actionId to txMeta.id and update srcTxHash
635
+ __classPrivateFieldGet(this, _BridgeStatusController_rekeyHistoryItem, "f").call(this, actionId, tradeTxMeta);
636
+ return tradeTxMeta;
637
637
  });
638
- // Pass txFee when gasIncluded is true to use the quote's gas fees
639
- // instead of re-estimating (which would fail for max native token swaps)
640
- const tradeTxMeta = await (0, transaction_1.submitEvmTransaction)({
641
- messenger: this.messenger,
642
- transactionType: isBridgeTx
643
- ? transaction_controller_1.TransactionType.bridge
644
- : transaction_controller_1.TransactionType.swap,
645
- trade: quoteResponse.trade,
646
- requireApproval,
647
- txFee: quoteResponse.quote.gasIncluded
648
- ? quoteResponse.quote.feeData.txFee
649
- : undefined,
650
- actionId,
638
+ }
639
+ }
640
+ catch (error) {
641
+ !quoteResponse.featureId &&
642
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Failed, undefined, {
643
+ error_message: error?.message,
644
+ ...preConfirmationProperties,
651
645
  });
652
- // On success, rekey from actionId to txMeta.id and update srcTxHash
653
- __classPrivateFieldGet(this, _BridgeStatusController_rekeyHistoryItem, "f").call(this, actionId, tradeTxMeta);
654
- return tradeTxMeta;
655
- });
646
+ throw error;
656
647
  }
657
648
  try {
658
649
  // For non-batch EVM transactions, history was already added/rekeyed above