@metamask-previews/bridge-controller 79.2.0-preview-c2ef75d18 → 79.2.0-preview-e81fe8853

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,10 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ### Added
11
-
12
- - Add Sentry quote-fetch and provider first-result performance traces ([#9899](https://github.com/MetaMask/core/pull/9899))
13
-
14
10
  ### Changed
15
11
 
16
12
  - Bump `@metamask/assets-controller` from `^13.1.2` to `^13.1.4` ([#9873](https://github.com/MetaMask/core/pull/9873), [#9886](https://github.com/MetaMask/core/pull/9886))
@@ -19,7 +19,6 @@ const contracts_1 = require("@ethersproject/contracts");
19
19
  const providers_1 = require("@ethersproject/providers");
20
20
  const metamask_eth_abis_1 = require("@metamask/metamask-eth-abis");
21
21
  const polling_controller_1 = require("@metamask/polling-controller");
22
- const uuid_1 = require("uuid");
23
22
  const quote_response_v1_to_v2_js_1 = require("./coercers/quote-response-v1-to-v2.cjs");
24
23
  const bridge_js_1 = require("./constants/bridge.cjs");
25
24
  const chains_js_1 = require("./constants/chains.cjs");
@@ -130,18 +129,6 @@ const metadata = {
130
129
  usedInUi: true,
131
130
  },
132
131
  };
133
- const QUOTE_ABORT_REASONS = new Set(Object.values(constants_js_1.AbortReason));
134
- const isExpectedQuoteAbort = (error, signal) => {
135
- if (signal?.aborted) {
136
- return true;
137
- }
138
- if (QUOTE_ABORT_REASONS.has(String(error))) {
139
- return true;
140
- }
141
- const errorText = error instanceof Error ? `${error.name} ${error.message}` : String(error);
142
- return (errorText.includes('AbortError') ||
143
- errorText.includes('FetchRequestCanceledException'));
144
- };
145
132
  const MESSENGER_EXPOSED_METHODS = [
146
133
  'updateBridgeQuoteRequestParams',
147
134
  'fetchQuotes',
@@ -517,9 +504,6 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
517
504
  __classPrivateFieldGet(this, _BridgeController_abortController, "f")?.abort(constants_js_1.AbortReason.NewQuoteRequest);
518
505
  __classPrivateFieldGet(this, _BridgeController_batchSellTradesAbortController, "f")?.abort(constants_js_1.AbortReason.NewQuoteRequest);
519
506
  __classPrivateFieldSet(this, _BridgeController_abortController, new AbortController(), "f");
520
- const quoteTraceStartTime = Date.now();
521
- const quoteTraceRequestId = (0, uuid_1.v4)();
522
- const quoteAbortSignal = __classPrivateFieldGet(this, _BridgeController_abortController, "f").signal;
523
507
  __classPrivateFieldGet(this, _BridgeController_fetchAssetExchangeRates, "f").call(this, quoteRequests).catch((error) => console.warn('Failed to fetch asset exchange rates', error));
524
508
  this.trackUnifiedSwapBridgeEvent(constants_js_1.UnifiedSwapBridgeEventName.QuotesRequested, context);
525
509
  const { sse, maxRefreshCount } = (0, feature_flags_js_1.getBridgeFeatureFlags)(this.messenger);
@@ -540,81 +524,43 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
540
524
  }
541
525
  });
542
526
  const jwt = await __classPrivateFieldGet(this, _BridgeController_getJwt, "f").call(this);
543
- const [firstQuoteRequest] = quoteRequests;
544
- let traceResult = 'error';
545
- let traceName = traces_js_1.TraceName.BatchSellQuotesFetched;
546
- if (!isBatchSellRequest) {
547
- traceName = (0, bridge_js_2.isCrossChain)(firstQuoteRequest.srcChainId, firstQuoteRequest.destChainId)
527
+ try {
528
+ const [firstQuoteRequest] = quoteRequests;
529
+ const unifiedSwapTraceName = (0, bridge_js_2.isCrossChain)(firstQuoteRequest.srcChainId, firstQuoteRequest.destChainId)
548
530
  ? traces_js_1.TraceName.BridgeQuotesFetched
549
531
  : traces_js_1.TraceName.SwapQuotesFetched;
550
- }
551
- const tracedProviders = new Set();
552
- const traceWithoutImpact = async (request) => {
553
- try {
554
- await __classPrivateFieldGet(this, _BridgeController_trace, "f").call(this, request, () => undefined);
555
- }
556
- catch {
557
- // Telemetry failures must not affect quote fetching or state updates.
558
- }
559
- };
560
- const traceProviderFirstResult = async (providerData) => {
561
- const provider = (0, properties_js_1.formatProviderLabel)(providerData);
562
- if (isBatchSellRequest || tracedProviders.has(provider)) {
563
- return;
564
- }
565
- tracedProviders.add(provider);
566
- await traceWithoutImpact({
567
- name: traces_js_1.TraceName.QuoteProviderFirstResult,
568
- startTime: quoteTraceStartTime,
532
+ await __classPrivateFieldGet(this, _BridgeController_trace, "f").call(this, {
533
+ name: isBatchSellRequest
534
+ ? traces_js_1.TraceName.BatchSellQuotesFetched
535
+ : unifiedSwapTraceName,
569
536
  data: {
570
- provider,
571
- request_id: quoteTraceRequestId,
572
- swap_type: (0, properties_js_1.getSwapType)(firstQuoteRequest.srcChainId, firstQuoteRequest.destChainId),
573
537
  srcChainId: (0, caip_formatters_js_1.formatChainIdToCaip)(firstQuoteRequest.srcChainId),
574
538
  destChainId: (0, caip_formatters_js_1.formatChainIdToCaip)(firstQuoteRequest.destChainId),
575
- result: 'success',
576
539
  },
577
- });
578
- };
579
- try {
580
- const selectedAccount = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getMultichainSelectedAccount).call(this, firstQuoteRequest.walletAddress);
581
- // This call is not awaited to prevent blocking quote fetching if the snap takes too long to respond
582
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
583
- __classPrivateFieldGet(this, _BridgeController_setMinimumBalanceForRentExemptionInLamports, "f").call(this, firstQuoteRequest.srcChainId, selectedAccount?.metadata?.snap?.id);
584
- // Use SSE if enabled and return early
585
- if (shouldStream || isBatchSellRequest) {
586
- const quoteCount = await __classPrivateFieldGet(this, _BridgeController_handleQuoteStreaming, "f").call(this, {
587
- quoteRequests,
588
- featureId: context.feature_id,
589
- jwt,
590
- selectedAccount,
591
- signal: quoteAbortSignal,
592
- traceProviderFirstResult,
593
- });
594
- if (quoteAbortSignal.aborted) {
595
- traceResult = 'cancelled';
540
+ }, async () => {
541
+ const selectedAccount = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getMultichainSelectedAccount).call(this, firstQuoteRequest.walletAddress);
542
+ // This call is not awaited to prevent blocking quote fetching if the snap takes too long to respond
543
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
544
+ __classPrivateFieldGet(this, _BridgeController_setMinimumBalanceForRentExemptionInLamports, "f").call(this, firstQuoteRequest.srcChainId, selectedAccount?.metadata?.snap?.id);
545
+ // Use SSE if enabled and return early
546
+ if (shouldStream || isBatchSellRequest) {
547
+ await __classPrivateFieldGet(this, _BridgeController_handleQuoteStreaming, "f").call(this, quoteRequests, context.feature_id, jwt, selectedAccount);
596
548
  return;
597
549
  }
598
- traceResult = quoteCount > 0 ? 'success' : 'no_quotes';
599
- }
600
- else {
601
550
  // Otherwise use regular fetch
602
- const quotes = await this.fetchQuotes(firstQuoteRequest, context.feature_id, quoteAbortSignal);
603
- for (const quote of quotes) {
604
- await traceProviderFirstResult(quote.quote);
605
- }
551
+ const quotes = await this.fetchQuotes(firstQuoteRequest, context.feature_id, __classPrivateFieldGet(this, _BridgeController_abortController, "f")?.signal);
606
552
  this.update((state) => {
607
553
  // Set the initial load time if this is the first fetch
608
554
  if (state.quotesRefreshCount ===
609
555
  bridge_js_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount &&
610
556
  __classPrivateFieldGet(this, _BridgeController_quotesFirstFetched, "f")) {
611
- state.quotesInitialLoadTime = Date.now() - __classPrivateFieldGet(this, _BridgeController_quotesFirstFetched, "f");
557
+ state.quotesInitialLoadTime =
558
+ Date.now() - __classPrivateFieldGet(this, _BridgeController_quotesFirstFetched, "f");
612
559
  }
613
560
  state.quotes = quotes.map(quote_response_v1_to_v2_js_1.toQuoteResponseV2);
614
561
  state.quotesLoadingStatus = types_js_1.RequestStatus.FETCHED;
615
562
  });
616
- traceResult = quotes.length > 0 ? 'success' : 'no_quotes';
617
- }
563
+ });
618
564
  }
619
565
  catch (error) {
620
566
  // Reset the quotes list if the fetch fails to avoid showing stale quotes
@@ -622,8 +568,14 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
622
568
  state.quotes = bridge_js_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;
623
569
  });
624
570
  // Ignore abort errors
625
- if (isExpectedQuoteAbort(error, quoteAbortSignal)) {
626
- traceResult = 'cancelled';
571
+ if (error.toString().includes('AbortError') ||
572
+ error.toString().includes('FetchRequestCanceledException') ||
573
+ [
574
+ constants_js_1.AbortReason.ResetState,
575
+ constants_js_1.AbortReason.NewQuoteRequest,
576
+ constants_js_1.AbortReason.QuoteRequestUpdated,
577
+ constants_js_1.AbortReason.TransactionSubmitted,
578
+ ].includes(error)) {
627
579
  // Exit the function early to prevent other state updates
628
580
  return;
629
581
  }
@@ -648,22 +600,6 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
648
600
  this.trackUnifiedSwapBridgeEvent(constants_js_1.UnifiedSwapBridgeEventName.QuotesError, context);
649
601
  console.log(`Failed to ${shouldStream ? 'stream' : 'fetch'} bridge quotes`, error);
650
602
  }
651
- finally {
652
- await traceWithoutImpact({
653
- name: traceName,
654
- startTime: quoteTraceStartTime,
655
- data: {
656
- srcChainId: (0, caip_formatters_js_1.formatChainIdToCaip)(firstQuoteRequest.srcChainId),
657
- destChainId: (0, caip_formatters_js_1.formatChainIdToCaip)(firstQuoteRequest.destChainId),
658
- ...(!isBatchSellRequest && {
659
- request_id: quoteTraceRequestId,
660
- swap_type: (0, properties_js_1.getSwapType)(firstQuoteRequest.srcChainId, firstQuoteRequest.destChainId),
661
- feature_id: context.feature_id,
662
- result: traceResult,
663
- }),
664
- },
665
- });
666
- }
667
603
  // Update refresh count after fetching, validation and fee calculation have completed
668
604
  this.update((state) => {
669
605
  state.quotesRefreshCount += 1;
@@ -678,7 +614,7 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
678
614
  this.stopAllPolling();
679
615
  }
680
616
  });
681
- _BridgeController_handleQuoteStreaming.set(this, async ({ quoteRequests, featureId, jwt, selectedAccount, signal, traceProviderFirstResult, }) => {
617
+ _BridgeController_handleQuoteStreaming.set(this, async (quoteRequests, featureId, jwt, selectedAccount) => {
682
618
  /**
683
619
  * Tracks the number of valid quotes received from the current stream, which is used
684
620
  * to determine when to clear the quotes list and set the initial load time
@@ -689,10 +625,9 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
689
625
  * before setting quotesLoadingStatus to FETCHED
690
626
  */
691
627
  const pendingFeeAppendPromises = new Set();
692
- await (0, fetch_js_1.fetchBridgeQuoteStream)(__classPrivateFieldGet(this, _BridgeController_fetchFn, "f"), quoteRequests, signal, featureId, __classPrivateFieldGet(this, _BridgeController_clientId, "f"), jwt, __classPrivateFieldGet(this, _BridgeController_config, "f").customBridgeApiBaseUrl ?? bridge_js_1.BRIDGE_PROD_API_BASE_URL, {
628
+ await (0, fetch_js_1.fetchBridgeQuoteStream)(__classPrivateFieldGet(this, _BridgeController_fetchFn, "f"), quoteRequests, __classPrivateFieldGet(this, _BridgeController_abortController, "f")?.signal, featureId, __classPrivateFieldGet(this, _BridgeController_clientId, "f"), jwt, __classPrivateFieldGet(this, _BridgeController_config, "f").customBridgeApiBaseUrl ?? bridge_js_1.BRIDGE_PROD_API_BASE_URL, {
693
629
  onQuoteValidationFailure: (validationFailures) => __classPrivateFieldGet(this, _BridgeController_trackQuoteValidationFailures, "f").call(this, validationFailures, featureId),
694
630
  onValidQuoteReceived: async (quote) => {
695
- await traceProviderFirstResult(quote.quote);
696
631
  const feeAppendPromise = (async () => {
697
632
  const quotesWithFees = await (0, quote_fees_js_1.appendFeesToQuotes)(quote.chainId, [quote], this.messenger, __classPrivateFieldGet(this, _BridgeController_getLayer1GasFee, "f"), selectedAccount);
698
633
  if (quotesWithFees.length > 0) {
@@ -756,7 +691,6 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
756
691
  });
757
692
  },
758
693
  }, __classPrivateFieldGet(this, _BridgeController_clientVersion, "f"));
759
- return validQuotesCounter;
760
694
  });
761
695
  _BridgeController_setMinimumBalanceForRentExemptionInLamports.set(this, async (srcChainId, snapId) => {
762
696
  if (!(0, bridge_js_2.isSolanaChainId)(srcChainId) || !snapId) {