@metamask-previews/bridge-controller 79.2.0-preview-f7d67b054 → 79.2.0-preview-3c77cf4
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 +0 -4
- package/dist/bridge-controller.cjs +29 -97
- package/dist/bridge-controller.cjs.map +1 -1
- package/dist/bridge-controller.d.cts.map +1 -1
- package/dist/bridge-controller.d.mts.map +1 -1
- package/dist/bridge-controller.mjs +30 -98
- package/dist/bridge-controller.mjs.map +1 -1
- package/dist/constants/traces.cjs +0 -1
- package/dist/constants/traces.cjs.map +1 -1
- package/dist/constants/traces.d.cts +0 -1
- package/dist/constants/traces.d.cts.map +1 -1
- package/dist/constants/traces.d.mts +0 -1
- package/dist/constants/traces.d.mts.map +1 -1
- package/dist/constants/traces.mjs +0 -1
- package/dist/constants/traces.mjs.map +1 -1
- package/package.json +1 -1
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,84 +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
|
-
|
|
544
|
-
|
|
545
|
-
|
|
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
|
-
|
|
552
|
-
|
|
553
|
-
|
|
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 = (providerData) => {
|
|
561
|
-
const provider = (0, properties_js_1.formatProviderLabel)(providerData);
|
|
562
|
-
if (isBatchSellRequest || tracedProviders.has(provider)) {
|
|
563
|
-
return;
|
|
564
|
-
}
|
|
565
|
-
tracedProviders.add(provider);
|
|
566
|
-
// Provider telemetry must not delay quote processing.
|
|
567
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
568
|
-
traceWithoutImpact({
|
|
569
|
-
name: traces_js_1.TraceName.QuoteProviderFirstResult,
|
|
570
|
-
startTime: quoteTraceStartTime,
|
|
532
|
+
await __classPrivateFieldGet(this, _BridgeController_trace, "f").call(this, {
|
|
533
|
+
name: isBatchSellRequest
|
|
534
|
+
? traces_js_1.TraceName.BatchSellQuotesFetched
|
|
535
|
+
: unifiedSwapTraceName,
|
|
571
536
|
data: {
|
|
572
|
-
provider,
|
|
573
|
-
feature_id: context.feature_id,
|
|
574
|
-
request_id: quoteTraceRequestId,
|
|
575
|
-
swap_type: (0, properties_js_1.getSwapType)(firstQuoteRequest.srcChainId, firstQuoteRequest.destChainId),
|
|
576
537
|
srcChainId: (0, caip_formatters_js_1.formatChainIdToCaip)(firstQuoteRequest.srcChainId),
|
|
577
538
|
destChainId: (0, caip_formatters_js_1.formatChainIdToCaip)(firstQuoteRequest.destChainId),
|
|
578
|
-
result: 'success',
|
|
579
539
|
},
|
|
580
|
-
})
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
if (shouldStream || isBatchSellRequest) {
|
|
589
|
-
const quoteCount = await __classPrivateFieldGet(this, _BridgeController_handleQuoteStreaming, "f").call(this, {
|
|
590
|
-
quoteRequests,
|
|
591
|
-
featureId: context.feature_id,
|
|
592
|
-
jwt,
|
|
593
|
-
selectedAccount,
|
|
594
|
-
signal: quoteAbortSignal,
|
|
595
|
-
traceProviderFirstResult,
|
|
596
|
-
});
|
|
597
|
-
if (quoteAbortSignal.aborted) {
|
|
598
|
-
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);
|
|
599
548
|
return;
|
|
600
549
|
}
|
|
601
|
-
traceResult = quoteCount > 0 ? 'success' : 'no_quotes';
|
|
602
|
-
}
|
|
603
|
-
else {
|
|
604
550
|
// Otherwise use regular fetch
|
|
605
|
-
const quotes = await this.fetchQuotes(firstQuoteRequest, context.feature_id,
|
|
606
|
-
for (const quote of quotes) {
|
|
607
|
-
traceProviderFirstResult(quote.quote);
|
|
608
|
-
}
|
|
551
|
+
const quotes = await this.fetchQuotes(firstQuoteRequest, context.feature_id, __classPrivateFieldGet(this, _BridgeController_abortController, "f")?.signal);
|
|
609
552
|
this.update((state) => {
|
|
610
553
|
// Set the initial load time if this is the first fetch
|
|
611
554
|
if (state.quotesRefreshCount ===
|
|
612
555
|
bridge_js_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount &&
|
|
613
556
|
__classPrivateFieldGet(this, _BridgeController_quotesFirstFetched, "f")) {
|
|
614
|
-
state.quotesInitialLoadTime =
|
|
557
|
+
state.quotesInitialLoadTime =
|
|
558
|
+
Date.now() - __classPrivateFieldGet(this, _BridgeController_quotesFirstFetched, "f");
|
|
615
559
|
}
|
|
616
560
|
state.quotes = quotes.map(quote_response_v1_to_v2_js_1.toQuoteResponseV2);
|
|
617
561
|
state.quotesLoadingStatus = types_js_1.RequestStatus.FETCHED;
|
|
618
562
|
});
|
|
619
|
-
|
|
620
|
-
}
|
|
563
|
+
});
|
|
621
564
|
}
|
|
622
565
|
catch (error) {
|
|
623
566
|
// Reset the quotes list if the fetch fails to avoid showing stale quotes
|
|
@@ -625,8 +568,14 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
625
568
|
state.quotes = bridge_js_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;
|
|
626
569
|
});
|
|
627
570
|
// Ignore abort errors
|
|
628
|
-
if (
|
|
629
|
-
|
|
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)) {
|
|
630
579
|
// Exit the function early to prevent other state updates
|
|
631
580
|
return;
|
|
632
581
|
}
|
|
@@ -651,21 +600,6 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
651
600
|
this.trackUnifiedSwapBridgeEvent(constants_js_1.UnifiedSwapBridgeEventName.QuotesError, context);
|
|
652
601
|
console.log(`Failed to ${shouldStream ? 'stream' : 'fetch'} bridge quotes`, error);
|
|
653
602
|
}
|
|
654
|
-
finally {
|
|
655
|
-
await traceWithoutImpact({
|
|
656
|
-
name: traceName,
|
|
657
|
-
startTime: quoteTraceStartTime,
|
|
658
|
-
data: {
|
|
659
|
-
srcChainId: (0, caip_formatters_js_1.formatChainIdToCaip)(firstQuoteRequest.srcChainId),
|
|
660
|
-
destChainId: (0, caip_formatters_js_1.formatChainIdToCaip)(firstQuoteRequest.destChainId),
|
|
661
|
-
...(!isBatchSellRequest && {
|
|
662
|
-
request_id: quoteTraceRequestId,
|
|
663
|
-
feature_id: context.feature_id,
|
|
664
|
-
result: traceResult,
|
|
665
|
-
}),
|
|
666
|
-
},
|
|
667
|
-
});
|
|
668
|
-
}
|
|
669
603
|
// Update refresh count after fetching, validation and fee calculation have completed
|
|
670
604
|
this.update((state) => {
|
|
671
605
|
state.quotesRefreshCount += 1;
|
|
@@ -680,7 +614,7 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
680
614
|
this.stopAllPolling();
|
|
681
615
|
}
|
|
682
616
|
});
|
|
683
|
-
_BridgeController_handleQuoteStreaming.set(this, async (
|
|
617
|
+
_BridgeController_handleQuoteStreaming.set(this, async (quoteRequests, featureId, jwt, selectedAccount) => {
|
|
684
618
|
/**
|
|
685
619
|
* Tracks the number of valid quotes received from the current stream, which is used
|
|
686
620
|
* to determine when to clear the quotes list and set the initial load time
|
|
@@ -691,14 +625,13 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
691
625
|
* before setting quotesLoadingStatus to FETCHED
|
|
692
626
|
*/
|
|
693
627
|
const pendingFeeAppendPromises = new Set();
|
|
694
|
-
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, {
|
|
695
629
|
onQuoteValidationFailure: (validationFailures) => __classPrivateFieldGet(this, _BridgeController_trackQuoteValidationFailures, "f").call(this, validationFailures, featureId),
|
|
696
630
|
onValidQuoteReceived: async (quote) => {
|
|
697
631
|
const feeAppendPromise = (async () => {
|
|
698
632
|
const quotesWithFees = await (0, quote_fees_js_1.appendFeesToQuotes)(quote.chainId, [quote], this.messenger, __classPrivateFieldGet(this, _BridgeController_getLayer1GasFee, "f"), selectedAccount);
|
|
699
633
|
if (quotesWithFees.length > 0) {
|
|
700
634
|
validQuotesCounter += 1;
|
|
701
|
-
traceProviderFirstResult(quote.quote);
|
|
702
635
|
}
|
|
703
636
|
this.update((state) => {
|
|
704
637
|
// Clear previous quotes and quotes load time when first quote in the current
|
|
@@ -758,7 +691,6 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
|
758
691
|
});
|
|
759
692
|
},
|
|
760
693
|
}, __classPrivateFieldGet(this, _BridgeController_clientVersion, "f"));
|
|
761
|
-
return validQuotesCounter;
|
|
762
694
|
});
|
|
763
695
|
_BridgeController_setMinimumBalanceForRentExemptionInLamports.set(this, async (srcChainId, snapId) => {
|
|
764
696
|
if (!(0, bridge_js_2.isSolanaChainId)(srcChainId) || !snapId) {
|