@metamask-previews/bridge-status-controller 64.2.0-preview-e776a73 → 64.2.0-preview-749d0638

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/bridge-status-controller.cjs +403 -15
  3. package/dist/bridge-status-controller.cjs.map +1 -1
  4. package/dist/bridge-status-controller.d.cts +16 -1
  5. package/dist/bridge-status-controller.d.cts.map +1 -1
  6. package/dist/bridge-status-controller.d.mts +16 -1
  7. package/dist/bridge-status-controller.d.mts.map +1 -1
  8. package/dist/bridge-status-controller.mjs +403 -15
  9. package/dist/bridge-status-controller.mjs.map +1 -1
  10. package/dist/types.cjs +9 -7
  11. package/dist/types.cjs.map +1 -1
  12. package/dist/types.d.cts +26 -16
  13. package/dist/types.d.cts.map +1 -1
  14. package/dist/types.d.mts +26 -16
  15. package/dist/types.d.mts.map +1 -1
  16. package/dist/types.mjs +9 -7
  17. package/dist/types.mjs.map +1 -1
  18. package/dist/utils/intent-api.cjs +73 -0
  19. package/dist/utils/intent-api.cjs.map +1 -0
  20. package/dist/utils/intent-api.d.cts +24 -0
  21. package/dist/utils/intent-api.d.cts.map +1 -0
  22. package/dist/utils/intent-api.d.mts +24 -0
  23. package/dist/utils/intent-api.d.mts.map +1 -0
  24. package/dist/utils/intent-api.mjs +68 -0
  25. package/dist/utils/intent-api.mjs.map +1 -0
  26. package/dist/utils/transaction.d.cts +21 -2
  27. package/dist/utils/transaction.d.cts.map +1 -1
  28. package/dist/utils/transaction.d.mts +21 -2
  29. package/dist/utils/transaction.d.mts.map +1 -1
  30. package/dist/utils/validators.cjs +23 -1
  31. package/dist/utils/validators.cjs.map +1 -1
  32. package/dist/utils/validators.d.cts +51 -0
  33. package/dist/utils/validators.d.cts.map +1 -1
  34. package/dist/utils/validators.d.mts +51 -0
  35. package/dist/utils/validators.d.mts.map +1 -1
  36. package/dist/utils/validators.mjs +22 -1
  37. package/dist/utils/validators.mjs.map +1 -1
  38. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
9
9
 
10
10
  ### Changed
11
11
 
12
+ - **BREAKING** Use CrossChain API instead of the intent manager package for intent order submission ([#6547](https://github.com/MetaMask/core/pull/6547))
12
13
  - Bump `@metamask/network-controller` from `^27.0.0` to `^27.1.0` ([#7534](https://github.com/MetaMask/core/pull/7534))
13
14
  - Bump `@metamask/controller-utils` from `^11.16.0` to `^11.17.0` ([#7534](https://github.com/MetaMask/core/pull/7534))
14
15
 
@@ -16,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
17
 
17
18
  ### Changed
18
19
 
20
+ >>>>>>> main
19
21
  - Bump `@metamask/transaction-controller` from `^62.5.0` to `^62.7.0` ([#7430](https://github.com/MetaMask/core/pull/7430), [#7494](https://github.com/MetaMask/core/pull/7494))
20
22
  - Bump `@metamask/bridge-controller` from `^64.1.0` to `^64.2.0` ([#7509](https://github.com/MetaMask/core/pull/7509))
21
23
 
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _BridgeStatusController_instances, _BridgeStatusController_pollingTokensByTxMetaId, _BridgeStatusController_clientId, _BridgeStatusController_fetchFn, _BridgeStatusController_config, _BridgeStatusController_addTransactionFn, _BridgeStatusController_addTransactionBatchFn, _BridgeStatusController_updateTransactionFn, _BridgeStatusController_estimateGasFeeFn, _BridgeStatusController_trace, _BridgeStatusController_markTxAsFailed, _BridgeStatusController_restartPollingForIncompleteHistoryItems, _BridgeStatusController_addTxToHistory, _BridgeStatusController_startPollingForTxId, _BridgeStatusController_getMultichainSelectedAccount, _BridgeStatusController_handleFetchFailure, _BridgeStatusController_fetchBridgeTxStatus, _BridgeStatusController_getSrcTxHash, _BridgeStatusController_updateSrcTxHash, _BridgeStatusController_wipeBridgeStatusByChainId, _BridgeStatusController_handleNonEvmTx, _BridgeStatusController_waitForHashAndReturnFinalTxMeta, _BridgeStatusController_handleApprovalTx, _BridgeStatusController_handleEvmTransaction, _BridgeStatusController_handleUSDTAllowanceReset, _BridgeStatusController_calculateGasFees, _BridgeStatusController_handleEvmTransactionBatch, _BridgeStatusController_trackUnifiedSwapBridgeEvent;
13
+ var _BridgeStatusController_instances, _BridgeStatusController_pollingTokensByTxMetaId, _BridgeStatusController_clientId, _BridgeStatusController_fetchFn, _BridgeStatusController_config, _BridgeStatusController_addTransactionFn, _BridgeStatusController_addTransactionBatchFn, _BridgeStatusController_updateTransactionFn, _BridgeStatusController_estimateGasFeeFn, _BridgeStatusController_trace, _BridgeStatusController_markTxAsFailed, _BridgeStatusController_restartPollingForIncompleteHistoryItems, _BridgeStatusController_addTxToHistory, _BridgeStatusController_startPollingForTxId, _BridgeStatusController_getMultichainSelectedAccount, _BridgeStatusController_handleFetchFailure, _BridgeStatusController_fetchBridgeTxStatus, _BridgeStatusController_fetchIntentOrderStatus, _BridgeStatusController_updateBridgeHistoryFromIntentOrder, _BridgeStatusController_getSrcTxHash, _BridgeStatusController_updateSrcTxHash, _BridgeStatusController_wipeBridgeStatusByChainId, _BridgeStatusController_handleNonEvmTx, _BridgeStatusController_waitForHashAndReturnFinalTxMeta, _BridgeStatusController_waitForTxConfirmation, _BridgeStatusController_handleApprovalTx, _BridgeStatusController_handleEvmTransaction, _BridgeStatusController_handleUSDTAllowanceReset, _BridgeStatusController_calculateGasFees, _BridgeStatusController_handleEvmTransactionBatch, _BridgeStatusController_convertBridgeQuoteToIntentQuote, _BridgeStatusController_mapIntentOrderStatusToTransactionStatus, _BridgeStatusController_trackUnifiedSwapBridgeEvent;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.BridgeStatusController = void 0;
16
16
  const bridge_controller_1 = require("@metamask/bridge-controller");
@@ -19,11 +19,13 @@ const polling_controller_1 = require("@metamask/polling-controller");
19
19
  const transaction_controller_1 = require("@metamask/transaction-controller");
20
20
  const utils_1 = require("@metamask/utils");
21
21
  const constants_1 = require("./constants.cjs");
22
+ const intent_api_1 = require("./utils/intent-api.cjs");
22
23
  const types_1 = require("./types.cjs");
23
24
  const bridge_status_1 = require("./utils/bridge-status.cjs");
24
25
  const gas_1 = require("./utils/gas.cjs");
25
26
  const metrics_1 = require("./utils/metrics.cjs");
26
27
  const transaction_1 = require("./utils/transaction.cjs");
28
+ const validators_1 = require("./utils/validators.cjs");
27
29
  const metadata = {
28
30
  // We want to persist the bridge status state so that we can show the proper data for the Activity list
29
31
  // basically match the behavior of TransactionController
@@ -180,6 +182,8 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
180
182
  // We know it's in progress but not the exact status yet
181
183
  const txHistoryItem = {
182
184
  txMetaId: bridgeTxMeta.id,
185
+ originalTransactionId: bridgeTxMeta
186
+ .originalTransactionId || bridgeTxMeta.id, // Keep original for intent transactions
183
187
  batchId: bridgeTxMeta.batchId,
184
188
  quote: quoteResponse.quote,
185
189
  startTime,
@@ -225,8 +229,9 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
225
229
  return;
226
230
  }
227
231
  const { quote } = txHistoryItem;
232
+ const isIntent = txId.startsWith('intent:');
228
233
  const isBridgeTx = (0, bridge_controller_1.isCrossChain)(quote.srcChainId, quote.destChainId);
229
- if (isBridgeTx) {
234
+ if (isBridgeTx || isIntent) {
230
235
  __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[txId] = this.startPolling({
231
236
  bridgeTxMetaId: txId,
232
237
  });
@@ -285,6 +290,11 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
285
290
  });
286
291
  _BridgeStatusController_fetchBridgeTxStatus.set(this, async ({ bridgeTxMetaId, }) => {
287
292
  const { txHistory } = this.state;
293
+ // Intent-based items: poll intent provider instead of Bridge API
294
+ if (bridgeTxMetaId.startsWith('intent:')) {
295
+ await __classPrivateFieldGet(this, _BridgeStatusController_fetchIntentOrderStatus, "f").call(this, { bridgeTxMetaId });
296
+ return;
297
+ }
288
298
  if ((0, bridge_status_1.shouldSkipFetchDueToFetchFailures)(txHistory[bridgeTxMetaId]?.attempts)) {
289
299
  return;
290
300
  }
@@ -341,8 +351,33 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
341
351
  }
342
352
  }
343
353
  }
344
- catch (e) {
345
- console.warn('Failed to fetch bridge tx status', e);
354
+ catch (error) {
355
+ console.warn('Failed to fetch bridge tx status', error);
356
+ __classPrivateFieldGet(this, _BridgeStatusController_handleFetchFailure, "f").call(this, bridgeTxMetaId);
357
+ }
358
+ });
359
+ _BridgeStatusController_fetchIntentOrderStatus.set(this, async ({ bridgeTxMetaId, }) => {
360
+ const { txHistory } = this.state;
361
+ const historyItem = txHistory[bridgeTxMetaId];
362
+ if (!historyItem) {
363
+ return;
364
+ }
365
+ // Backoff handling
366
+ if ((0, bridge_status_1.shouldSkipFetchDueToFetchFailures)(historyItem.attempts)) {
367
+ return;
368
+ }
369
+ try {
370
+ const orderId = bridgeTxMetaId.replace(/^intent:/u, '');
371
+ const { srcChainId } = historyItem.quote;
372
+ // Extract provider name from order metadata or default to empty
373
+ const providerName = historyItem.quote.intent?.protocol ?? '';
374
+ const intentApi = new intent_api_1.IntentApiImpl(__classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl, __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"));
375
+ const intentOrder = await intentApi.getOrderStatus(orderId, providerName, srcChainId.toString(), __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f"));
376
+ // Update bridge history with intent order status
377
+ __classPrivateFieldGet(this, _BridgeStatusController_instances, "m", _BridgeStatusController_updateBridgeHistoryFromIntentOrder).call(this, bridgeTxMetaId, intentOrder, historyItem);
378
+ }
379
+ catch (error) {
380
+ console.error('Failed to fetch intent order status:', error);
346
381
  __classPrivateFieldGet(this, _BridgeStatusController_handleFetchFailure, "f").call(this, bridgeTxMetaId);
347
382
  }
348
383
  });
@@ -433,6 +468,36 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
433
468
  }
434
469
  return finalTransactionMeta;
435
470
  });
471
+ // Waits until a given transaction (by id) reaches confirmed/finalized status or fails/times out.
472
+ _BridgeStatusController_waitForTxConfirmation.set(this, async (txId, { timeoutMs = 5 * 60000, // 5 minutes default
473
+ pollMs = 2000, } = {}) => {
474
+ const start = Date.now();
475
+ // Poll the TransactionController state for status changes
476
+ // We intentionally keep this simple to avoid extra wiring/subscriptions in this controller
477
+ // and because we only need it for the rare intent+approval path.
478
+ while (true) {
479
+ const { transactions } = this.messenger.call('TransactionController:getState');
480
+ const meta = transactions.find((tx) => tx.id === txId);
481
+ if (meta) {
482
+ // Treat both 'confirmed' and 'finalized' as success to match TC lifecycle
483
+ if (meta.status === transaction_controller_1.TransactionStatus.confirmed ||
484
+ // Some environments move directly to finalized
485
+ transaction_controller_1.TransactionStatus.finalized ===
486
+ meta.status) {
487
+ return meta;
488
+ }
489
+ if (meta.status === transaction_controller_1.TransactionStatus.failed ||
490
+ meta.status === transaction_controller_1.TransactionStatus.dropped ||
491
+ meta.status === transaction_controller_1.TransactionStatus.rejected) {
492
+ throw new Error('Approval transaction did not confirm');
493
+ }
494
+ }
495
+ if (Date.now() - start > timeoutMs) {
496
+ throw new Error('Timed out waiting for approval confirmation');
497
+ }
498
+ await new Promise((resolve) => setTimeout(resolve, pollMs));
499
+ }
500
+ });
436
501
  _BridgeStatusController_handleApprovalTx.set(this, async (isBridgeTx, srcChainId, approval, resetApproval, requireApproval) => {
437
502
  if (approval) {
438
503
  const approveTx = async () => {
@@ -486,11 +551,17 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
486
551
  type: transactionType,
487
552
  origin: 'metamask',
488
553
  };
554
+ // Exclude gasLimit from trade to avoid type issues (it can be null)
555
+ const { gasLimit: tradeGasLimit, ...tradeWithoutGasLimit } = trade;
489
556
  const transactionParams = {
490
- ...trade,
557
+ ...tradeWithoutGasLimit,
491
558
  chainId: hexChainId,
492
- gasLimit: trade.gasLimit?.toString(),
493
- gas: trade.gasLimit?.toString(),
559
+ // Only add gasLimit and gas if they're valid (not undefined/null/zero)
560
+ ...(tradeGasLimit &&
561
+ tradeGasLimit !== 0 && {
562
+ gasLimit: tradeGasLimit.toString(),
563
+ gas: tradeGasLimit.toString(),
564
+ }),
494
565
  };
495
566
  const transactionParamsWithMaxGas = {
496
567
  ...transactionParams,
@@ -737,6 +808,168 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
737
808
  }
738
809
  return txMeta;
739
810
  };
811
+ /**
812
+ * UI-signed intent submission (fast path): the UI generates the EIP-712 signature and calls this with the raw signature.
813
+ * Here we submit the order to the intent provider and create a synthetic history entry for UX.
814
+ *
815
+ * @param params - Object containing intent submission parameters
816
+ * @param params.quoteResponse - Quote carrying intent data
817
+ * @param params.signature - Hex signature produced by eth_signTypedData_v4
818
+ * @param params.accountAddress - The EOA submitting the order
819
+ * @returns A lightweight TransactionMeta-like object for history linking
820
+ */
821
+ this.submitIntent = async (params) => {
822
+ const { quoteResponse, signature, accountAddress } = params;
823
+ // Build pre-confirmation properties for error tracking parity with submitTx
824
+ const account = __classPrivateFieldGet(this, _BridgeStatusController_instances, "m", _BridgeStatusController_getMultichainSelectedAccount).call(this, accountAddress);
825
+ const isHardwareAccount = Boolean(account) && (0, bridge_controller_1.isHardwareWallet)(account);
826
+ const preConfirmationProperties = (0, metrics_1.getPreConfirmationPropertiesFromQuote)(quoteResponse, false, isHardwareAccount);
827
+ try {
828
+ const { intent } = quoteResponse
829
+ .quote;
830
+ if (!intent) {
831
+ throw new Error('submitIntent: missing intent data');
832
+ }
833
+ // If backend provided an approval tx for this intent quote, submit it first (on-chain),
834
+ // then proceed with off-chain intent submission.
835
+ let approvalTxId;
836
+ if (quoteResponse.approval) {
837
+ const isBridgeTx = (0, bridge_controller_1.isCrossChain)(quoteResponse.quote.srcChainId, quoteResponse.quote.destChainId);
838
+ // Handle approval silently for better UX in intent flows
839
+ const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleApprovalTx, "f").call(this, isBridgeTx, quoteResponse.quote.srcChainId, quoteResponse.approval && (0, bridge_controller_1.isEvmTxData)(quoteResponse.approval)
840
+ ? quoteResponse.approval
841
+ : undefined, quoteResponse.resetApproval,
842
+ /* requireApproval */ false);
843
+ approvalTxId = approvalTxMeta?.id;
844
+ // Optionally wait for approval confirmation with timeout and graceful fallback
845
+ // Intent order can be created before allowance is mined, but waiting helps avoid MEV issues
846
+ if (approvalTxId) {
847
+ try {
848
+ // Wait with a shorter timeout and continue if it fails
849
+ await __classPrivateFieldGet(this, _BridgeStatusController_waitForTxConfirmation, "f").call(this, approvalTxId, {
850
+ timeoutMs: 30000, // 30 seconds instead of 5 minutes
851
+ pollMs: 3000, // Poll less frequently to avoid rate limits
852
+ });
853
+ }
854
+ catch (error) {
855
+ // Log but don't throw - continue with intent order submission
856
+ console.warn('Approval confirmation failed, continuing with intent submission:', error);
857
+ }
858
+ }
859
+ }
860
+ // Create intent quote from bridge quote response
861
+ const intentQuote = __classPrivateFieldGet(this, _BridgeStatusController_instances, "m", _BridgeStatusController_convertBridgeQuoteToIntentQuote).call(this, quoteResponse, intent);
862
+ const chainId = quoteResponse.quote.srcChainId;
863
+ const submissionParams = {
864
+ srcChainId: chainId.toString(),
865
+ quoteId: intentQuote.id,
866
+ signature,
867
+ order: intentQuote.metadata.order,
868
+ userAddress: accountAddress,
869
+ aggregatorId: 'cowswap',
870
+ };
871
+ const intentApi = new intent_api_1.IntentApiImpl(__classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl, __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"));
872
+ const intentOrder = (await intentApi.submitIntent(submissionParams, __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f")));
873
+ const orderUid = intentOrder.id;
874
+ // Determine transaction type: swap for same-chain, bridge for cross-chain
875
+ const isCrossChainTx = (0, bridge_controller_1.isCrossChain)(quoteResponse.quote.srcChainId, quoteResponse.quote.destChainId);
876
+ const transactionType = isCrossChainTx
877
+ ? transaction_controller_1.TransactionType.bridge
878
+ : transaction_controller_1.TransactionType.swap;
879
+ // Create actual transaction in Transaction Controller first
880
+ const networkClientId = this.messenger.call('NetworkController:findNetworkClientIdByChainId', (0, bridge_controller_1.formatChainIdToHex)(chainId));
881
+ const intentTransactionParams = {
882
+ chainId: (0, bridge_controller_1.formatChainIdToHex)(chainId),
883
+ from: accountAddress,
884
+ to: intent.settlementContract ??
885
+ '0x9008D19f58AAbd9eD0D60971565AA8510560ab41', // Default settlement contract
886
+ data: `0x${orderUid.slice(-8)}`, // Use last 8 chars of orderUid to make each transaction unique
887
+ value: '0x0',
888
+ gas: '0x5208', // Minimal gas for display purposes
889
+ gasPrice: '0x3b9aca00', // 1 Gwei - will be converted to EIP-1559 fees if network supports it
890
+ };
891
+ const { transactionMeta: txMetaPromise } = await __classPrivateFieldGet(this, _BridgeStatusController_addTransactionFn, "f").call(this, intentTransactionParams, {
892
+ origin: 'metamask',
893
+ actionId: (0, transaction_1.generateActionId)(),
894
+ requireApproval: false,
895
+ networkClientId,
896
+ type: transactionType,
897
+ skipInitialGasEstimate: true,
898
+ swaps: {
899
+ meta: {
900
+ // Add token symbols from quoteResponse for proper display
901
+ sourceTokenSymbol: quoteResponse.quote.srcAsset.symbol,
902
+ destinationTokenSymbol: quoteResponse.quote.destAsset.symbol,
903
+ sourceTokenAmount: quoteResponse.quote.srcTokenAmount,
904
+ destinationTokenAmount: quoteResponse.quote.destTokenAmount,
905
+ sourceTokenDecimals: quoteResponse.quote.srcAsset.decimals,
906
+ destinationTokenDecimals: quoteResponse.quote.destAsset.decimals,
907
+ sourceTokenAddress: quoteResponse.quote.srcAsset.address,
908
+ destinationTokenAddress: quoteResponse.quote.destAsset.address,
909
+ swapTokenValue: quoteResponse.sentAmount.amount,
910
+ approvalTxId,
911
+ swapMetaData: {
912
+ isIntentTx: true,
913
+ orderUid,
914
+ intentType: isCrossChainTx ? 'bridge' : 'swap',
915
+ },
916
+ },
917
+ },
918
+ });
919
+ const intentTxMeta = txMetaPromise;
920
+ // Map intent order status to TransactionController status
921
+ const initialTransactionStatus = __classPrivateFieldGet(this, _BridgeStatusController_instances, "m", _BridgeStatusController_mapIntentOrderStatusToTransactionStatus).call(this, intentOrder.status);
922
+ // Update transaction with proper initial status based on intent order
923
+ const statusUpdatedTxMeta = {
924
+ ...intentTxMeta,
925
+ status: initialTransactionStatus,
926
+ };
927
+ // Update with actual transaction metadata
928
+ const syntheticMeta = {
929
+ ...statusUpdatedTxMeta,
930
+ isIntentTx: true,
931
+ orderUid,
932
+ intentType: isCrossChainTx ? 'bridge' : 'swap',
933
+ };
934
+ // Record in bridge history with actual transaction metadata
935
+ try {
936
+ // Use 'intent:' prefix for intent transactions
937
+ const bridgeHistoryKey = `intent:${orderUid}`;
938
+ // Create a bridge transaction metadata that includes the original txId
939
+ const bridgeTxMetaForHistory = {
940
+ ...syntheticMeta,
941
+ id: bridgeHistoryKey, // Use intent: prefix for bridge history key
942
+ originalTransactionId: syntheticMeta.id, // Keep original txId for TransactionController updates
943
+ };
944
+ __classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
945
+ accountAddress,
946
+ bridgeTxMeta: bridgeTxMetaForHistory,
947
+ statusRequest: {
948
+ ...(0, transaction_1.getStatusRequestParams)(quoteResponse),
949
+ srcTxHash: syntheticMeta.hash ?? '',
950
+ },
951
+ quoteResponse,
952
+ slippagePercentage: 0,
953
+ isStxEnabled: false,
954
+ approvalTxId,
955
+ });
956
+ // Start polling using the intent: prefixed key to route to intent manager
957
+ __classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, bridgeHistoryKey);
958
+ }
959
+ catch (error) {
960
+ console.error('📝 [submitIntent] Failed to add to bridge history', error);
961
+ // non-fatal but log the error
962
+ }
963
+ return syntheticMeta;
964
+ }
965
+ catch (error) {
966
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Failed, undefined, {
967
+ error_message: error?.message,
968
+ ...preConfirmationProperties,
969
+ });
970
+ throw error;
971
+ }
972
+ };
740
973
  /**
741
974
  * Tracks post-submission events for a cross-chain swap based on the history item
742
975
  *
@@ -762,13 +995,12 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
762
995
  const requestParamProperties = (0, metrics_1.getRequestParamFromHistory)(historyItem);
763
996
  // Always publish StatusValidationFailed event, regardless of featureId
764
997
  if (eventName === bridge_controller_1.UnifiedSwapBridgeEventName.StatusValidationFailed) {
765
- const { chain_id_source, chain_id_destination, token_address_source, token_address_destination, } = requestParamProperties;
766
998
  this.messenger.call('BridgeController:trackUnifiedSwapBridgeEvent', eventName, {
767
999
  ...baseProperties,
768
- chain_id_source,
769
- chain_id_destination,
770
- token_address_source,
771
- token_address_destination,
1000
+ chain_id_source: requestParamProperties.chain_id_source,
1001
+ chain_id_destination: requestParamProperties.chain_id_destination,
1002
+ token_address_source: requestParamProperties.token_address_source,
1003
+ token_address_destination: requestParamProperties.token_address_destination,
772
1004
  refresh_count: historyItem.attempts?.counter ?? 0,
773
1005
  });
774
1006
  return;
@@ -779,8 +1011,8 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
779
1011
  }
780
1012
  const selectedAccount = this.messenger.call('AccountsController:getAccountByAddress', historyItem.account);
781
1013
  const { transactions } = this.messenger.call('TransactionController:getState');
782
- const txMeta = transactions?.find(({ id }) => id === txMetaId);
783
- const approvalTxMeta = transactions?.find(({ id }) => id === historyItem.approvalTxId);
1014
+ const txMeta = transactions?.find((tx) => tx.id === txMetaId);
1015
+ const approvalTxMeta = transactions?.find((tx) => tx.id === historyItem.approvalTxId);
784
1016
  const requiredEventProperties = {
785
1017
  ...baseProperties,
786
1018
  ...requestParamProperties,
@@ -807,12 +1039,18 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
807
1039
  this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:wipeBridgeStatus`, this.wipeBridgeStatus.bind(this));
808
1040
  this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:resetState`, this.resetState.bind(this));
809
1041
  this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:submitTx`, this.submitTx.bind(this));
1042
+ this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:submitIntent`, this.submitIntent.bind(this));
810
1043
  this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:restartPollingForFailedAttempts`, this.restartPollingForFailedAttempts.bind(this));
811
1044
  this.messenger.registerActionHandler(`${constants_1.BRIDGE_STATUS_CONTROLLER_NAME}:getBridgeHistoryItemByTxMetaId`, this.getBridgeHistoryItemByTxMetaId.bind(this));
812
1045
  // Set interval
813
1046
  this.setIntervalLength(constants_1.REFRESH_INTERVAL_MS);
814
1047
  this.messenger.subscribe('TransactionController:transactionFailed', ({ transactionMeta }) => {
815
1048
  const { type, status, id } = transactionMeta;
1049
+ // Skip intent transactions - they have their own tracking via CoW API
1050
+ if (transactionMeta
1051
+ .swapMetaData?.isIntentTx) {
1052
+ return;
1053
+ }
816
1054
  if (type &&
817
1055
  [
818
1056
  transaction_controller_1.TransactionType.bridge,
@@ -849,7 +1087,157 @@ class BridgeStatusController extends (0, polling_controller_1.StaticIntervalPoll
849
1087
  }
850
1088
  }
851
1089
  exports.BridgeStatusController = BridgeStatusController;
852
- _BridgeStatusController_pollingTokensByTxMetaId = new WeakMap(), _BridgeStatusController_clientId = new WeakMap(), _BridgeStatusController_fetchFn = new WeakMap(), _BridgeStatusController_config = new WeakMap(), _BridgeStatusController_addTransactionFn = new WeakMap(), _BridgeStatusController_addTransactionBatchFn = new WeakMap(), _BridgeStatusController_updateTransactionFn = new WeakMap(), _BridgeStatusController_estimateGasFeeFn = new WeakMap(), _BridgeStatusController_trace = new WeakMap(), _BridgeStatusController_markTxAsFailed = new WeakMap(), _BridgeStatusController_restartPollingForIncompleteHistoryItems = new WeakMap(), _BridgeStatusController_addTxToHistory = new WeakMap(), _BridgeStatusController_startPollingForTxId = new WeakMap(), _BridgeStatusController_handleFetchFailure = new WeakMap(), _BridgeStatusController_fetchBridgeTxStatus = new WeakMap(), _BridgeStatusController_getSrcTxHash = new WeakMap(), _BridgeStatusController_updateSrcTxHash = new WeakMap(), _BridgeStatusController_wipeBridgeStatusByChainId = new WeakMap(), _BridgeStatusController_handleNonEvmTx = new WeakMap(), _BridgeStatusController_waitForHashAndReturnFinalTxMeta = new WeakMap(), _BridgeStatusController_handleApprovalTx = new WeakMap(), _BridgeStatusController_handleEvmTransaction = new WeakMap(), _BridgeStatusController_handleUSDTAllowanceReset = new WeakMap(), _BridgeStatusController_calculateGasFees = new WeakMap(), _BridgeStatusController_handleEvmTransactionBatch = new WeakMap(), _BridgeStatusController_trackUnifiedSwapBridgeEvent = new WeakMap(), _BridgeStatusController_instances = new WeakSet(), _BridgeStatusController_getMultichainSelectedAccount = function _BridgeStatusController_getMultichainSelectedAccount(accountAddress) {
1090
+ _BridgeStatusController_pollingTokensByTxMetaId = new WeakMap(), _BridgeStatusController_clientId = new WeakMap(), _BridgeStatusController_fetchFn = new WeakMap(), _BridgeStatusController_config = new WeakMap(), _BridgeStatusController_addTransactionFn = new WeakMap(), _BridgeStatusController_addTransactionBatchFn = new WeakMap(), _BridgeStatusController_updateTransactionFn = new WeakMap(), _BridgeStatusController_estimateGasFeeFn = new WeakMap(), _BridgeStatusController_trace = new WeakMap(), _BridgeStatusController_markTxAsFailed = new WeakMap(), _BridgeStatusController_restartPollingForIncompleteHistoryItems = new WeakMap(), _BridgeStatusController_addTxToHistory = new WeakMap(), _BridgeStatusController_startPollingForTxId = new WeakMap(), _BridgeStatusController_handleFetchFailure = new WeakMap(), _BridgeStatusController_fetchBridgeTxStatus = new WeakMap(), _BridgeStatusController_fetchIntentOrderStatus = new WeakMap(), _BridgeStatusController_getSrcTxHash = new WeakMap(), _BridgeStatusController_updateSrcTxHash = new WeakMap(), _BridgeStatusController_wipeBridgeStatusByChainId = new WeakMap(), _BridgeStatusController_handleNonEvmTx = new WeakMap(), _BridgeStatusController_waitForHashAndReturnFinalTxMeta = new WeakMap(), _BridgeStatusController_waitForTxConfirmation = new WeakMap(), _BridgeStatusController_handleApprovalTx = new WeakMap(), _BridgeStatusController_handleEvmTransaction = new WeakMap(), _BridgeStatusController_handleUSDTAllowanceReset = new WeakMap(), _BridgeStatusController_calculateGasFees = new WeakMap(), _BridgeStatusController_handleEvmTransactionBatch = new WeakMap(), _BridgeStatusController_trackUnifiedSwapBridgeEvent = new WeakMap(), _BridgeStatusController_instances = new WeakSet(), _BridgeStatusController_getMultichainSelectedAccount = function _BridgeStatusController_getMultichainSelectedAccount(accountAddress) {
853
1091
  return this.messenger.call('AccountsController:getAccountByAddress', accountAddress);
1092
+ }, _BridgeStatusController_updateBridgeHistoryFromIntentOrder = function _BridgeStatusController_updateBridgeHistoryFromIntentOrder(bridgeTxMetaId, intentOrder, historyItem) {
1093
+ const { srcChainId } = historyItem.quote;
1094
+ // Map intent order status to bridge status using enum values
1095
+ let statusType;
1096
+ const isComplete = [
1097
+ validators_1.IntentOrderStatus.CONFIRMED,
1098
+ validators_1.IntentOrderStatus.COMPLETED,
1099
+ ].includes(intentOrder.status);
1100
+ const isFailed = [
1101
+ validators_1.IntentOrderStatus.FAILED,
1102
+ validators_1.IntentOrderStatus.EXPIRED,
1103
+ ].includes(intentOrder.status);
1104
+ const isPending = [validators_1.IntentOrderStatus.PENDING].includes(intentOrder.status);
1105
+ const isSubmitted = [validators_1.IntentOrderStatus.SUBMITTED].includes(intentOrder.status);
1106
+ if (isComplete) {
1107
+ statusType = bridge_controller_1.StatusTypes.COMPLETE;
1108
+ }
1109
+ else if (isFailed) {
1110
+ statusType = bridge_controller_1.StatusTypes.FAILED;
1111
+ }
1112
+ else if (isPending) {
1113
+ statusType = bridge_controller_1.StatusTypes.PENDING;
1114
+ }
1115
+ else if (isSubmitted) {
1116
+ statusType = bridge_controller_1.StatusTypes.SUBMITTED;
1117
+ }
1118
+ else {
1119
+ statusType = bridge_controller_1.StatusTypes.UNKNOWN;
1120
+ }
1121
+ // Extract transaction hashes from intent order
1122
+ const txHash = intentOrder.txHash ?? '';
1123
+ // Check metadata for additional transaction hashes
1124
+ const metadataTxHashes = Array.isArray(intentOrder.metadata.txHashes)
1125
+ ? intentOrder.metadata.txHashes
1126
+ : [];
1127
+ let allHashes;
1128
+ if (metadataTxHashes.length > 0) {
1129
+ allHashes = metadataTxHashes;
1130
+ }
1131
+ else if (txHash) {
1132
+ allHashes = [txHash];
1133
+ }
1134
+ else {
1135
+ allHashes = [];
1136
+ }
1137
+ const newStatus = {
1138
+ status: statusType,
1139
+ srcChain: {
1140
+ chainId: srcChainId,
1141
+ txHash: txHash ?? historyItem.status.srcChain.txHash ?? '',
1142
+ },
1143
+ };
1144
+ const newBridgeHistoryItem = {
1145
+ ...historyItem,
1146
+ status: newStatus,
1147
+ completionTime: newStatus.status === bridge_controller_1.StatusTypes.COMPLETE ||
1148
+ newStatus.status === bridge_controller_1.StatusTypes.FAILED
1149
+ ? Date.now()
1150
+ : undefined,
1151
+ attempts: undefined,
1152
+ srcTxHashes: allHashes.length > 0
1153
+ ? Array.from(new Set([...(historyItem.srcTxHashes ?? []), ...allHashes]))
1154
+ : historyItem.srcTxHashes,
1155
+ };
1156
+ this.update((state) => {
1157
+ state.txHistory[bridgeTxMetaId] = newBridgeHistoryItem;
1158
+ });
1159
+ // Update the actual transaction in TransactionController to sync with intent status
1160
+ // Use the original transaction ID (not the intent: prefixed bridge history key)
1161
+ const originalTxId = historyItem.originalTransactionId ?? historyItem.txMetaId;
1162
+ if (originalTxId && !originalTxId.startsWith('intent:')) {
1163
+ try {
1164
+ const transactionStatus = __classPrivateFieldGet(this, _BridgeStatusController_instances, "m", _BridgeStatusController_mapIntentOrderStatusToTransactionStatus).call(this, intentOrder.status);
1165
+ // Merge with existing TransactionMeta to avoid wiping required fields
1166
+ const { transactions } = this.messenger.call('TransactionController:getState');
1167
+ const existingTxMeta = transactions.find((tx) => tx.id === originalTxId);
1168
+ if (existingTxMeta) {
1169
+ const updatedTxMeta = {
1170
+ ...existingTxMeta,
1171
+ status: transactionStatus,
1172
+ ...(txHash ? { hash: txHash } : {}),
1173
+ ...(txHash
1174
+ ? {
1175
+ txReceipt: {
1176
+ ...existingTxMeta.txReceipt,
1177
+ transactionHash: txHash,
1178
+ status: (isComplete ? '0x1' : '0x0'),
1179
+ },
1180
+ }
1181
+ : {}),
1182
+ };
1183
+ __classPrivateFieldGet(this, _BridgeStatusController_updateTransactionFn, "f").call(this, updatedTxMeta, `BridgeStatusController - Intent order status updated: ${intentOrder.status}`);
1184
+ }
1185
+ else {
1186
+ console.warn('📝 [fetchIntentOrderStatus] Skipping update; transaction not found', { originalTxId, bridgeHistoryKey: bridgeTxMetaId });
1187
+ }
1188
+ }
1189
+ catch (error) {
1190
+ console.error('📝 [fetchIntentOrderStatus] Failed to update transaction status', {
1191
+ originalTxId,
1192
+ bridgeHistoryKey: bridgeTxMetaId,
1193
+ error,
1194
+ });
1195
+ }
1196
+ }
1197
+ const pollingToken = __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
1198
+ const isFinal = newStatus.status === bridge_controller_1.StatusTypes.COMPLETE ||
1199
+ newStatus.status === bridge_controller_1.StatusTypes.FAILED;
1200
+ if (isFinal && pollingToken) {
1201
+ this.stopPollingByPollingToken(pollingToken);
1202
+ delete __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[bridgeTxMetaId];
1203
+ if (newStatus.status === bridge_controller_1.StatusTypes.COMPLETE) {
1204
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Completed, bridgeTxMetaId);
1205
+ }
1206
+ else if (newStatus.status === bridge_controller_1.StatusTypes.FAILED) {
1207
+ __classPrivateFieldGet(this, _BridgeStatusController_trackUnifiedSwapBridgeEvent, "f").call(this, bridge_controller_1.UnifiedSwapBridgeEventName.Failed, bridgeTxMetaId);
1208
+ }
1209
+ }
1210
+ }, _BridgeStatusController_convertBridgeQuoteToIntentQuote = function _BridgeStatusController_convertBridgeQuoteToIntentQuote(quoteResponse, intent) {
1211
+ return {
1212
+ id: `bridge-${Date.now()}`,
1213
+ provider: intent.protocol,
1214
+ srcAmount: quoteResponse.quote.srcTokenAmount,
1215
+ destAmount: quoteResponse.quote.destTokenAmount,
1216
+ estimatedGas: '21000',
1217
+ estimatedTime: 300, // 5 minutes
1218
+ priceImpact: 0,
1219
+ fees: [],
1220
+ validUntil: Date.now() + 300000, // 5 minutes from now
1221
+ metadata: {
1222
+ order: intent.order,
1223
+ settlementContract: intent.settlementContract ?? '',
1224
+ chainId: quoteResponse.quote.srcChainId,
1225
+ bridgeQuote: quoteResponse,
1226
+ },
1227
+ };
1228
+ }, _BridgeStatusController_mapIntentOrderStatusToTransactionStatus = function _BridgeStatusController_mapIntentOrderStatusToTransactionStatus(intentStatus) {
1229
+ switch (intentStatus) {
1230
+ case validators_1.IntentOrderStatus.PENDING:
1231
+ case validators_1.IntentOrderStatus.SUBMITTED:
1232
+ return transaction_controller_1.TransactionStatus.submitted;
1233
+ case validators_1.IntentOrderStatus.CONFIRMED:
1234
+ case validators_1.IntentOrderStatus.COMPLETED:
1235
+ return transaction_controller_1.TransactionStatus.confirmed;
1236
+ case validators_1.IntentOrderStatus.FAILED:
1237
+ case validators_1.IntentOrderStatus.EXPIRED:
1238
+ return transaction_controller_1.TransactionStatus.failed;
1239
+ default:
1240
+ return transaction_controller_1.TransactionStatus.submitted;
1241
+ }
854
1242
  };
855
1243
  //# sourceMappingURL=bridge-status-controller.cjs.map