@metamask/bridge-status-controller 69.0.0 → 70.0.1
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 +22 -1
- package/dist/bridge-status-controller.cjs +115 -354
- package/dist/bridge-status-controller.cjs.map +1 -1
- package/dist/bridge-status-controller.d.cts +3 -5
- package/dist/bridge-status-controller.d.cts.map +1 -1
- package/dist/bridge-status-controller.d.mts +3 -5
- package/dist/bridge-status-controller.d.mts.map +1 -1
- package/dist/bridge-status-controller.intent.cjs +12 -25
- package/dist/bridge-status-controller.intent.cjs.map +1 -1
- package/dist/bridge-status-controller.intent.d.cts +3 -14
- package/dist/bridge-status-controller.intent.d.cts.map +1 -1
- package/dist/bridge-status-controller.intent.d.mts +3 -14
- package/dist/bridge-status-controller.intent.d.mts.map +1 -1
- package/dist/bridge-status-controller.intent.mjs +12 -25
- package/dist/bridge-status-controller.intent.mjs.map +1 -1
- package/dist/bridge-status-controller.mjs +118 -357
- package/dist/bridge-status-controller.mjs.map +1 -1
- package/dist/index.cjs +1 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +0 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +0 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +11 -5
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +11 -5
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils/accounts.cjs +8 -0
- package/dist/utils/accounts.cjs.map +1 -0
- package/dist/utils/accounts.d.cts +36 -0
- package/dist/utils/accounts.d.cts.map +1 -0
- package/dist/utils/accounts.d.mts +36 -0
- package/dist/utils/accounts.d.mts.map +1 -0
- package/dist/utils/accounts.mjs +4 -0
- package/dist/utils/accounts.mjs.map +1 -0
- package/dist/utils/authentication.cjs +15 -0
- package/dist/utils/authentication.cjs.map +1 -0
- package/dist/utils/authentication.d.cts +3 -0
- package/dist/utils/authentication.d.cts.map +1 -0
- package/dist/utils/authentication.d.mts +3 -0
- package/dist/utils/authentication.d.mts.map +1 -0
- package/dist/utils/authentication.mjs +11 -0
- package/dist/utils/authentication.mjs.map +1 -0
- package/dist/utils/bridge-status.cjs +17 -1
- package/dist/utils/bridge-status.cjs.map +1 -1
- package/dist/utils/bridge-status.d.cts +8 -2
- package/dist/utils/bridge-status.d.cts.map +1 -1
- package/dist/utils/bridge-status.d.mts +8 -2
- package/dist/utils/bridge-status.d.mts.map +1 -1
- package/dist/utils/bridge-status.mjs +15 -0
- package/dist/utils/bridge-status.mjs.map +1 -1
- package/dist/utils/bridge.cjs +16 -0
- package/dist/utils/bridge.cjs.map +1 -0
- package/dist/utils/bridge.d.cts +10 -0
- package/dist/utils/bridge.d.cts.map +1 -0
- package/dist/utils/bridge.d.mts +10 -0
- package/dist/utils/bridge.d.mts.map +1 -0
- package/dist/utils/bridge.mjs +11 -0
- package/dist/utils/bridge.mjs.map +1 -0
- package/dist/utils/gas.cjs +1 -61
- package/dist/utils/gas.cjs.map +1 -1
- package/dist/utils/gas.d.cts +3 -26
- package/dist/utils/gas.d.cts.map +1 -1
- package/dist/utils/gas.d.mts +3 -26
- package/dist/utils/gas.d.mts.map +1 -1
- package/dist/utils/gas.mjs +0 -58
- package/dist/utils/gas.mjs.map +1 -1
- package/dist/utils/history.cjs +98 -0
- package/dist/utils/history.cjs.map +1 -0
- package/dist/utils/history.d.cts +22 -0
- package/dist/utils/history.d.cts.map +1 -0
- package/dist/utils/history.d.mts +22 -0
- package/dist/utils/history.d.mts.map +1 -0
- package/dist/utils/history.mjs +91 -0
- package/dist/utils/history.mjs.map +1 -0
- package/dist/utils/intent-api.cjs +41 -26
- package/dist/utils/intent-api.cjs.map +1 -1
- package/dist/utils/intent-api.d.cts +16 -3
- package/dist/utils/intent-api.d.cts.map +1 -1
- package/dist/utils/intent-api.d.mts +16 -3
- package/dist/utils/intent-api.d.mts.map +1 -1
- package/dist/utils/intent-api.mjs +38 -25
- package/dist/utils/intent-api.mjs.map +1 -1
- package/dist/utils/keyring.cjs +12 -0
- package/dist/utils/keyring.cjs.map +1 -0
- package/dist/utils/keyring.d.cts +8 -0
- package/dist/utils/keyring.d.cts.map +1 -0
- package/dist/utils/keyring.d.mts +8 -0
- package/dist/utils/keyring.d.mts.map +1 -0
- package/dist/utils/keyring.mjs +8 -0
- package/dist/utils/keyring.mjs.map +1 -0
- package/dist/utils/network.cjs +17 -0
- package/dist/utils/network.cjs.map +1 -0
- package/dist/utils/network.d.cts +5 -0
- package/dist/utils/network.d.cts.map +1 -0
- package/dist/utils/network.d.mts +5 -0
- package/dist/utils/network.d.mts.map +1 -0
- package/dist/utils/network.mjs +12 -0
- package/dist/utils/network.mjs.map +1 -0
- package/dist/utils/snaps.cjs +146 -1
- package/dist/utils/snaps.cjs.map +1 -1
- package/dist/utils/snaps.d.cts +48 -0
- package/dist/utils/snaps.d.cts.map +1 -1
- package/dist/utils/snaps.d.mts +48 -0
- package/dist/utils/snaps.d.mts.map +1 -1
- package/dist/utils/snaps.mjs +141 -0
- package/dist/utils/snaps.mjs.map +1 -1
- package/dist/utils/trace.cjs +31 -0
- package/dist/utils/trace.cjs.map +1 -0
- package/dist/utils/trace.d.cts +17 -0
- package/dist/utils/trace.d.cts.map +1 -0
- package/dist/utils/trace.d.mts +17 -0
- package/dist/utils/trace.d.mts.map +1 -0
- package/dist/utils/trace.mjs +26 -0
- package/dist/utils/trace.mjs.map +1 -0
- package/dist/utils/transaction.cjs +239 -184
- package/dist/utils/transaction.cjs.map +1 -1
- package/dist/utils/transaction.d.cts +85 -236
- package/dist/utils/transaction.d.cts.map +1 -1
- package/dist/utils/transaction.d.mts +85 -236
- package/dist/utils/transaction.d.mts.map +1 -1
- package/dist/utils/transaction.mjs +226 -176
- package/dist/utils/transaction.mjs.map +1 -1
- package/dist/utils/validators.d.cts +2 -2
- package/dist/utils/validators.d.mts +2 -2
- package/package.json +3 -3
|
@@ -9,21 +9,26 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
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");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var
|
|
13
|
-
import { formatChainIdToHex, isNonEvmChainId, StatusTypes, UnifiedSwapBridgeEventName,
|
|
14
|
-
import { toHex } from "@metamask/controller-utils";
|
|
15
|
-
import { SignTypedDataVersion } from "@metamask/keyring-controller";
|
|
12
|
+
var _BridgeStatusController_pollingTokensByTxMetaId, _BridgeStatusController_intentManager, _BridgeStatusController_clientId, _BridgeStatusController_fetchFn, _BridgeStatusController_config, _BridgeStatusController_addTransactionBatchFn, _BridgeStatusController_trace, _BridgeStatusController_markTxAsFailed, _BridgeStatusController_restartPollingForIncompleteHistoryItems, _BridgeStatusController_addTxToHistory, _BridgeStatusController_rekeyHistoryItem, _BridgeStatusController_startPollingForTxId, _BridgeStatusController_handleFetchFailure, _BridgeStatusController_fetchBridgeTxStatus, _BridgeStatusController_getSrcTxHash, _BridgeStatusController_updateSrcTxHash, _BridgeStatusController_wipeBridgeStatusByChainId, _BridgeStatusController_handleApprovalTx, _BridgeStatusController_handleEvmTransactionBatch, _BridgeStatusController_trackUnifiedSwapBridgeEvent;
|
|
13
|
+
import { formatChainIdToHex, isNonEvmChainId, StatusTypes, UnifiedSwapBridgeEventName, isCrossChain, isTronChainId, isEvmTxData, isHardwareWallet, MetricsActionType, MetaMetricsSwapsEventSource, isBitcoinTrade, isTronTrade, PollingStatus } from "@metamask/bridge-controller";
|
|
16
14
|
import { StaticIntervalPollingController } from "@metamask/polling-controller";
|
|
17
|
-
import { TransactionStatus, TransactionType } from "@metamask/transaction-controller";
|
|
15
|
+
import { TransactionStatus, TransactionType, TransactionController } from "@metamask/transaction-controller";
|
|
18
16
|
import { numberToHex } from "@metamask/utils";
|
|
19
17
|
import { IntentManager } from "./bridge-status-controller.intent.mjs";
|
|
20
|
-
import { BRIDGE_PROD_API_BASE_URL, BRIDGE_STATUS_CONTROLLER_NAME, DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE, MAX_ATTEMPTS, REFRESH_INTERVAL_MS
|
|
18
|
+
import { BRIDGE_PROD_API_BASE_URL, BRIDGE_STATUS_CONTROLLER_NAME, DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE, MAX_ATTEMPTS, REFRESH_INTERVAL_MS } from "./constants.mjs";
|
|
21
19
|
import { BridgeClientId } from "./types.mjs";
|
|
20
|
+
import { getAccountByAddress } from "./utils/accounts.mjs";
|
|
21
|
+
import { getJwt } from "./utils/authentication.mjs";
|
|
22
|
+
import { stopPollingForQuotes, trackMetricsEvent } from "./utils/bridge.mjs";
|
|
22
23
|
import { fetchBridgeTxStatus, getStatusRequestWithSrcTxHash, shouldSkipFetchDueToFetchFailures } from "./utils/bridge-status.mjs";
|
|
23
|
-
import {
|
|
24
|
-
import { mapIntentOrderStatusToTransactionStatus } from "./utils/intent-api.mjs";
|
|
24
|
+
import { getInitialHistoryItem, rekeyHistoryItemInState, shouldPollHistoryItem } from "./utils/history.mjs";
|
|
25
|
+
import { getIntentFromQuote, mapIntentOrderStatusToTransactionStatus, postSubmitOrder } from "./utils/intent-api.mjs";
|
|
26
|
+
import { signTypedMessage } from "./utils/keyring.mjs";
|
|
25
27
|
import { getFinalizedTxProperties, getPriceImpactFromQuote, getRequestMetadataFromHistory, getRequestParamFromHistory, getTradeDataFromHistory, getEVMTxPropertiesFromTransactionMeta, getTxStatusesFromHistory, getPreConfirmationPropertiesFromQuote } from "./utils/metrics.mjs";
|
|
26
|
-
import {
|
|
28
|
+
import { getNetworkClientIdByChainId, getSelectedChainId } from "./utils/network.mjs";
|
|
29
|
+
import { handleNonEvmTx } from "./utils/snaps.mjs";
|
|
30
|
+
import { getApprovalTraceParams, getTraceParams } from "./utils/trace.mjs";
|
|
31
|
+
import { getAddTransactionBatchParams, handleApprovalDelay, handleMobileHardwareWalletDelay, generateActionId, waitForTxConfirmation, getTransactionMetaById, addTransactionBatch, addSyntheticTransaction, getTransactions, submitEvmTransaction, checkIsDelegatedAccount } from "./utils/transaction.mjs";
|
|
27
32
|
const metadata = {
|
|
28
33
|
// We want to persist the bridge status state so that we can show the proper data for the Activity list
|
|
29
34
|
// basically match the behavior of TransactionController
|
|
@@ -35,7 +40,7 @@ const metadata = {
|
|
|
35
40
|
},
|
|
36
41
|
};
|
|
37
42
|
export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
38
|
-
constructor({ messenger, state, clientId, fetchFn,
|
|
43
|
+
constructor({ messenger, state, clientId, fetchFn, addTransactionBatchFn, config, traceFn, }) {
|
|
39
44
|
super({
|
|
40
45
|
name: BRIDGE_STATUS_CONTROLLER_NAME,
|
|
41
46
|
metadata,
|
|
@@ -46,16 +51,12 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
46
51
|
...state,
|
|
47
52
|
},
|
|
48
53
|
});
|
|
49
|
-
_BridgeStatusController_instances.add(this);
|
|
50
54
|
_BridgeStatusController_pollingTokensByTxMetaId.set(this, {});
|
|
51
55
|
_BridgeStatusController_intentManager.set(this, void 0);
|
|
52
56
|
_BridgeStatusController_clientId.set(this, void 0);
|
|
53
57
|
_BridgeStatusController_fetchFn.set(this, void 0);
|
|
54
58
|
_BridgeStatusController_config.set(this, void 0);
|
|
55
|
-
_BridgeStatusController_addTransactionFn.set(this, void 0);
|
|
56
59
|
_BridgeStatusController_addTransactionBatchFn.set(this, void 0);
|
|
57
|
-
_BridgeStatusController_updateTransactionFn.set(this, void 0);
|
|
58
|
-
_BridgeStatusController_estimateGasFeeFn.set(this, void 0);
|
|
59
60
|
_BridgeStatusController_trace.set(this, void 0);
|
|
60
61
|
// Mark tx as failed in txHistory if either the approval or trade fails
|
|
61
62
|
_BridgeStatusController_markTxAsFailed.set(this, ({ id: txMetaId, actionId, }) => {
|
|
@@ -90,9 +91,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
90
91
|
});
|
|
91
92
|
}
|
|
92
93
|
else {
|
|
93
|
-
const
|
|
94
|
-
const selectedNetworkClient = this.messenger.call('NetworkController:getNetworkClientById', selectedNetworkClientId);
|
|
95
|
-
const selectedChainId = selectedNetworkClient.configuration.chainId;
|
|
94
|
+
const selectedChainId = getSelectedChainId(this.messenger);
|
|
96
95
|
__classPrivateFieldGet(this, _BridgeStatusController_wipeBridgeStatusByChainId, "f").call(this, address, selectedChainId);
|
|
97
96
|
}
|
|
98
97
|
};
|
|
@@ -134,7 +133,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
134
133
|
}
|
|
135
134
|
});
|
|
136
135
|
// Restart polling if it was stopped and this tx still needs status updates
|
|
137
|
-
if (
|
|
136
|
+
if (shouldPollHistoryItem(historyItem)) {
|
|
138
137
|
// Check if polling was stopped (no active polling token)
|
|
139
138
|
const existingPollingToken = __classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[targetTxMetaId];
|
|
140
139
|
if (!existingPollingToken) {
|
|
@@ -142,7 +141,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
142
141
|
__classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, targetTxMetaId);
|
|
143
142
|
// Track polling manually restarted event
|
|
144
143
|
if (!historyItem.featureId) {
|
|
145
|
-
const selectedAccount = this.messenger
|
|
144
|
+
const selectedAccount = getAccountByAddress(this.messenger, historyItem.account);
|
|
146
145
|
const requestParams = getRequestParamFromHistory(historyItem);
|
|
147
146
|
const requestMetadata = getRequestMetadataFromHistory(historyItem, selectedAccount);
|
|
148
147
|
const { security_warnings: _, ...metadataWithoutWarnings } = requestMetadata;
|
|
@@ -191,7 +190,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
191
190
|
})
|
|
192
191
|
// Only restart polling for items that still require status updates
|
|
193
192
|
.filter((historyItem) => {
|
|
194
|
-
return
|
|
193
|
+
return shouldPollHistoryItem(historyItem);
|
|
195
194
|
});
|
|
196
195
|
incompleteHistoryItems.forEach((historyItem) => {
|
|
197
196
|
const bridgeTxMetaId = historyItem.txMetaId;
|
|
@@ -204,51 +203,8 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
204
203
|
__classPrivateFieldGet(this, _BridgeStatusController_startPollingForTxId, "f").call(this, bridgeTxMetaId);
|
|
205
204
|
});
|
|
206
205
|
});
|
|
207
|
-
_BridgeStatusController_addTxToHistory.set(this, (
|
|
208
|
-
const {
|
|
209
|
-
// Determine the key for this history item:
|
|
210
|
-
// - For pre-submission (non-batch EVM): use actionId
|
|
211
|
-
// - For post-submission or other cases: use bridgeTxMeta.id
|
|
212
|
-
const historyKey = getHistoryKey(actionId, bridgeTxMeta?.id);
|
|
213
|
-
// Write all non-status fields to state so we can reference the quote in Activity list without the Bridge API
|
|
214
|
-
// We know it's in progress but not the exact status yet
|
|
215
|
-
const txHistoryItem = {
|
|
216
|
-
txMetaId: bridgeTxMeta?.id,
|
|
217
|
-
actionId,
|
|
218
|
-
originalTransactionId: bridgeTxMeta
|
|
219
|
-
?.originalTransactionId || bridgeTxMeta?.id, // Keep original for intent transactions
|
|
220
|
-
batchId: bridgeTxMeta?.batchId,
|
|
221
|
-
quote: quoteResponse.quote,
|
|
222
|
-
startTime,
|
|
223
|
-
estimatedProcessingTimeInSeconds: quoteResponse.estimatedProcessingTimeInSeconds,
|
|
224
|
-
slippagePercentage,
|
|
225
|
-
pricingData: {
|
|
226
|
-
amountSent: quoteResponse.sentAmount?.amount ?? '0',
|
|
227
|
-
amountSentInUsd: quoteResponse.sentAmount?.usd ?? undefined,
|
|
228
|
-
quotedGasInUsd: quoteResponse.gasFee?.effective?.usd ?? undefined,
|
|
229
|
-
quotedReturnInUsd: quoteResponse.toTokenAmount?.usd ?? undefined,
|
|
230
|
-
quotedGasAmount: quoteResponse.gasFee?.effective?.amount ?? undefined,
|
|
231
|
-
},
|
|
232
|
-
initialDestAssetBalance,
|
|
233
|
-
targetContractAddress,
|
|
234
|
-
account: selectedAddress,
|
|
235
|
-
status: {
|
|
236
|
-
// We always have a PENDING status when we start polling for a tx, don't need the Bridge API for that
|
|
237
|
-
// Also we know the bare minimum fields for status at this point in time
|
|
238
|
-
status: StatusTypes.PENDING,
|
|
239
|
-
srcChain: {
|
|
240
|
-
chainId: statusRequest.srcChainId,
|
|
241
|
-
txHash: statusRequest.srcTxHash,
|
|
242
|
-
},
|
|
243
|
-
},
|
|
244
|
-
hasApprovalTx: Boolean(quoteResponse.approval),
|
|
245
|
-
approvalTxId,
|
|
246
|
-
isStxEnabled: Boolean(isStxEnabled),
|
|
247
|
-
featureId: quoteResponse.featureId,
|
|
248
|
-
location,
|
|
249
|
-
...(abTests && { abTests }),
|
|
250
|
-
...(activeAbTests && { activeAbTests }),
|
|
251
|
-
};
|
|
206
|
+
_BridgeStatusController_addTxToHistory.set(this, (...args) => {
|
|
207
|
+
const { historyKey, txHistoryItem } = getInitialHistoryItem(...args);
|
|
252
208
|
this.update((state) => {
|
|
253
209
|
// Use actionId as key for pre-submission, or txMeta.id for post-submission
|
|
254
210
|
state.txHistory[historyKey] = txHistoryItem;
|
|
@@ -278,18 +234,12 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
278
234
|
if (!txHistoryItem) {
|
|
279
235
|
return;
|
|
280
236
|
}
|
|
281
|
-
if (
|
|
237
|
+
if (shouldPollHistoryItem(txHistoryItem)) {
|
|
282
238
|
__classPrivateFieldGet(this, _BridgeStatusController_pollingTokensByTxMetaId, "f")[txId] = this.startPolling({
|
|
283
239
|
bridgeTxMetaId: txId,
|
|
284
240
|
});
|
|
285
241
|
}
|
|
286
242
|
});
|
|
287
|
-
_BridgeStatusController_shouldPollHistoryItem.set(this, (historyItem) => {
|
|
288
|
-
const isIntent = Boolean(historyItem?.quote?.intent);
|
|
289
|
-
const isBridgeTx = isCrossChain(historyItem.quote.srcChainId, historyItem.quote.destChainId);
|
|
290
|
-
const isTronTx = isTronChainId(historyItem.quote.srcChainId);
|
|
291
|
-
return [isBridgeTx, isIntent, isTronTx].some(Boolean);
|
|
292
|
-
});
|
|
293
243
|
/**
|
|
294
244
|
* @deprecated For EVM/Solana swap/bridge txs we add tx to history in submitTx()
|
|
295
245
|
* For Solana swap/bridge we start polling in submitTx()
|
|
@@ -341,7 +291,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
341
291
|
// Track max polling reached event
|
|
342
292
|
const historyItem = this.state.txHistory[bridgeTxMetaId];
|
|
343
293
|
if (historyItem && !historyItem.featureId) {
|
|
344
|
-
const selectedAccount = this.messenger
|
|
294
|
+
const selectedAccount = getAccountByAddress(this.messenger, historyItem.account);
|
|
345
295
|
const requestParams = getRequestParamFromHistory(historyItem);
|
|
346
296
|
const requestMetadata = getRequestMetadataFromHistory(historyItem, selectedAccount);
|
|
347
297
|
const { security_warnings: _, ...metadataWithoutWarnings } = requestMetadata;
|
|
@@ -397,7 +347,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
397
347
|
}
|
|
398
348
|
__classPrivateFieldGet(this, _BridgeStatusController_updateSrcTxHash, "f").call(this, bridgeTxMetaId, srcTxHash);
|
|
399
349
|
const statusRequest = getStatusRequestWithSrcTxHash(historyItem.quote, srcTxHash);
|
|
400
|
-
const response = await fetchBridgeTxStatus(statusRequest, __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f"), await
|
|
350
|
+
const response = await fetchBridgeTxStatus(statusRequest, __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f"), await getJwt(this.messenger), __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"), __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl);
|
|
401
351
|
status = response.status;
|
|
402
352
|
validationFailures = response.validationFailures;
|
|
403
353
|
}
|
|
@@ -453,16 +403,6 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
453
403
|
__classPrivateFieldGet(this, _BridgeStatusController_handleFetchFailure, "f").call(this, bridgeTxMetaId);
|
|
454
404
|
}
|
|
455
405
|
});
|
|
456
|
-
_BridgeStatusController_getJwt.set(this, async () => {
|
|
457
|
-
try {
|
|
458
|
-
const token = await this.messenger.call('AuthenticationController:getBearerToken');
|
|
459
|
-
return token;
|
|
460
|
-
}
|
|
461
|
-
catch (error) {
|
|
462
|
-
console.error('Error getting JWT token for bridge-api request', error);
|
|
463
|
-
return undefined;
|
|
464
|
-
}
|
|
465
|
-
});
|
|
466
406
|
_BridgeStatusController_getSrcTxHash.set(this, (bridgeTxMetaId) => {
|
|
467
407
|
const { txHistory } = this.state;
|
|
468
408
|
// Prefer the srcTxHash from bridgeStatusState so we don't have to l ook up in TransactionController
|
|
@@ -472,8 +412,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
472
412
|
return srcTxHash;
|
|
473
413
|
}
|
|
474
414
|
// Look up in TransactionController if txMeta has been updated with the srcTxHash
|
|
475
|
-
const
|
|
476
|
-
const txMeta = txControllerState.transactions.find((tx) => tx.id === bridgeTxMetaId);
|
|
415
|
+
const txMeta = getTransactionMetaById(this.messenger, bridgeTxMetaId);
|
|
477
416
|
return txMeta?.hash;
|
|
478
417
|
});
|
|
479
418
|
_BridgeStatusController_updateSrcTxHash.set(this, (bridgeTxMetaId, srcTxHash) => {
|
|
@@ -512,57 +451,18 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
512
451
|
* TX SUBMISSION HANDLING
|
|
513
452
|
*******************************************************
|
|
514
453
|
*/
|
|
515
|
-
|
|
516
|
-
* Submits the transaction to the snap using the new unified ClientRequest interface
|
|
517
|
-
* Works for all non-EVM chains (Solana, BTC, Tron)
|
|
518
|
-
* This adds an approval tx to the ApprovalsController in the background
|
|
519
|
-
* The client needs to handle the approval tx by redirecting to the confirmation page with the approvalTxId in the URL
|
|
520
|
-
*
|
|
521
|
-
* @param trade - The trade data (can be approval or main trade)
|
|
522
|
-
* @param quoteResponse - The quote response containing metadata
|
|
523
|
-
* @param selectedAccount - The account to submit the transaction for
|
|
524
|
-
* @returns The transaction meta
|
|
525
|
-
*/
|
|
526
|
-
_BridgeStatusController_handleNonEvmTx.set(this, async (trade, quoteResponse, selectedAccount) => {
|
|
527
|
-
if (!selectedAccount.metadata?.snap?.id) {
|
|
528
|
-
throw new Error('Failed to submit cross-chain swap transaction: undefined snap id');
|
|
529
|
-
}
|
|
530
|
-
const request = getClientRequest(trade, quoteResponse.quote.srcChainId, selectedAccount);
|
|
531
|
-
const requestResponse = (await this.messenger.call('SnapController:handleRequest', request));
|
|
532
|
-
// Create quote response with the specified trade
|
|
533
|
-
// This allows the same method to handle both approvals and main trades
|
|
534
|
-
const txQuoteResponse = {
|
|
535
|
-
...quoteResponse,
|
|
536
|
-
trade,
|
|
537
|
-
};
|
|
538
|
-
const txMeta = handleNonEvmTxResponse(requestResponse, txQuoteResponse, selectedAccount);
|
|
539
|
-
// TODO remove this eventually, just returning it now to match extension behavior
|
|
540
|
-
// OR if the snap can propagate the snapRequestId or keyringReqId to the ApprovalsController, this can return the approvalTxId instead and clients won't need to subscribe to the ApprovalsController state to redirect
|
|
541
|
-
return txMeta;
|
|
542
|
-
});
|
|
543
|
-
_BridgeStatusController_waitForHashAndReturnFinalTxMeta.set(this, async (hashPromise) => {
|
|
544
|
-
const transactionHash = await hashPromise;
|
|
545
|
-
const finalTransactionMeta = this.messenger
|
|
546
|
-
.call('TransactionController:getState')
|
|
547
|
-
.transactions.find((tx) => tx.hash === transactionHash);
|
|
548
|
-
if (!finalTransactionMeta) {
|
|
549
|
-
throw new Error('Failed to submit cross-chain swap tx: txMeta for txHash was not found');
|
|
550
|
-
}
|
|
551
|
-
return finalTransactionMeta;
|
|
552
|
-
});
|
|
553
|
-
// Waits until a given transaction (by id) reaches confirmed/finalized status or fails/times out.
|
|
554
|
-
_BridgeStatusController_waitForTxConfirmation.set(this, async (txId, { timeoutMs = 5 * 60000, // 5 minutes default
|
|
555
|
-
pollMs = 3000, } = {}) => {
|
|
556
|
-
return await waitForTxConfirmation(this.messenger, txId, {
|
|
557
|
-
timeoutMs,
|
|
558
|
-
pollMs,
|
|
559
|
-
});
|
|
560
|
-
});
|
|
561
|
-
_BridgeStatusController_handleApprovalTx.set(this, async (isBridgeTx, srcChainId, approval, resetApproval, requireApproval) => {
|
|
454
|
+
_BridgeStatusController_handleApprovalTx.set(this, async (quoteResponse, isBridgeTx, srcChainId, approval, resetApproval, requireApproval) => {
|
|
562
455
|
if (approval && isEvmTxData(approval)) {
|
|
563
456
|
const approveTx = async () => {
|
|
564
|
-
|
|
565
|
-
|
|
457
|
+
if (resetApproval) {
|
|
458
|
+
await submitEvmTransaction({
|
|
459
|
+
messenger: this.messenger,
|
|
460
|
+
transactionType: TransactionType.bridgeApproval,
|
|
461
|
+
trade: resetApproval,
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
const approvalTxMeta = await submitEvmTransaction({
|
|
465
|
+
messenger: this.messenger,
|
|
566
466
|
transactionType: isBridgeTx
|
|
567
467
|
? TransactionType.bridgeApproval
|
|
568
468
|
: TransactionType.swapApproval,
|
|
@@ -572,101 +472,11 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
572
472
|
await handleApprovalDelay(srcChainId);
|
|
573
473
|
return approvalTxMeta;
|
|
574
474
|
};
|
|
575
|
-
return await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this,
|
|
576
|
-
name: isBridgeTx
|
|
577
|
-
? TraceName.BridgeTransactionApprovalCompleted
|
|
578
|
-
: TraceName.SwapTransactionApprovalCompleted,
|
|
579
|
-
data: {
|
|
580
|
-
srcChainId: formatChainIdToCaip(srcChainId),
|
|
581
|
-
stxEnabled: false,
|
|
582
|
-
},
|
|
583
|
-
}, approveTx);
|
|
475
|
+
return await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, getApprovalTraceParams(quoteResponse, false), approveTx);
|
|
584
476
|
}
|
|
585
477
|
return undefined;
|
|
586
478
|
});
|
|
587
|
-
|
|
588
|
-
* Submits an EVM transaction to the TransactionController
|
|
589
|
-
*
|
|
590
|
-
* @param params - The parameters for the transaction
|
|
591
|
-
* @param params.transactionType - The type of transaction to submit
|
|
592
|
-
* @param params.trade - The trade data to confirm
|
|
593
|
-
* @param params.requireApproval - Whether to require approval for the transaction
|
|
594
|
-
* @param params.txFee - Optional gas fee parameters from the quote (used when gasIncluded is true)
|
|
595
|
-
* @param params.txFee.maxFeePerGas - The maximum fee per gas from the quote
|
|
596
|
-
* @param params.txFee.maxPriorityFeePerGas - The maximum priority fee per gas from the quote
|
|
597
|
-
* @param params.actionId - Optional actionId for pre-submission history (if not provided, one is generated)
|
|
598
|
-
* @returns The transaction meta
|
|
599
|
-
*/
|
|
600
|
-
_BridgeStatusController_handleEvmTransaction.set(this, async ({ transactionType, trade, requireApproval = false, txFee, actionId: providedActionId, }) => {
|
|
601
|
-
// Use provided actionId (for pre-submission history) or generate one
|
|
602
|
-
const actionId = providedActionId ?? generateActionId().toString();
|
|
603
|
-
const selectedAccount = this.messenger.call('AccountsController:getAccountByAddress', trade.from);
|
|
604
|
-
if (!selectedAccount) {
|
|
605
|
-
throw new Error('Failed to submit cross-chain swap transaction: unknown account in trade data');
|
|
606
|
-
}
|
|
607
|
-
const hexChainId = formatChainIdToHex(trade.chainId);
|
|
608
|
-
const networkClientId = this.messenger.call('NetworkController:findNetworkClientIdByChainId', hexChainId);
|
|
609
|
-
const requestOptions = {
|
|
610
|
-
actionId,
|
|
611
|
-
networkClientId,
|
|
612
|
-
requireApproval,
|
|
613
|
-
type: transactionType,
|
|
614
|
-
origin: 'metamask',
|
|
615
|
-
};
|
|
616
|
-
// Exclude gasLimit from trade to avoid type issues (it can be null)
|
|
617
|
-
const { gasLimit: tradeGasLimit, ...tradeWithoutGasLimit } = trade;
|
|
618
|
-
const transactionParams = {
|
|
619
|
-
...tradeWithoutGasLimit,
|
|
620
|
-
chainId: hexChainId,
|
|
621
|
-
// Only add gasLimit and gas if they're valid (not undefined/null/zero)
|
|
622
|
-
...(tradeGasLimit &&
|
|
623
|
-
tradeGasLimit !== 0 && {
|
|
624
|
-
gasLimit: tradeGasLimit.toString(),
|
|
625
|
-
gas: tradeGasLimit.toString(),
|
|
626
|
-
}),
|
|
627
|
-
};
|
|
628
|
-
const transactionParamsWithMaxGas = {
|
|
629
|
-
...transactionParams,
|
|
630
|
-
...(await __classPrivateFieldGet(this, _BridgeStatusController_calculateGasFees, "f").call(this, transactionParams, networkClientId, hexChainId, txFee)),
|
|
631
|
-
};
|
|
632
|
-
const { result } = await __classPrivateFieldGet(this, _BridgeStatusController_addTransactionFn, "f").call(this, transactionParamsWithMaxGas, requestOptions);
|
|
633
|
-
return await __classPrivateFieldGet(this, _BridgeStatusController_waitForHashAndReturnFinalTxMeta, "f").call(this, result);
|
|
634
|
-
});
|
|
635
|
-
_BridgeStatusController_handleUSDTAllowanceReset.set(this, async (resetApproval) => {
|
|
636
|
-
if (resetApproval) {
|
|
637
|
-
await __classPrivateFieldGet(this, _BridgeStatusController_handleEvmTransaction, "f").call(this, {
|
|
638
|
-
transactionType: TransactionType.bridgeApproval,
|
|
639
|
-
trade: resetApproval,
|
|
640
|
-
});
|
|
641
|
-
}
|
|
642
|
-
});
|
|
643
|
-
_BridgeStatusController_calculateGasFees.set(this, async (transactionParams, networkClientId, chainId, txFee) => {
|
|
644
|
-
const { gas } = transactionParams;
|
|
645
|
-
// If txFee is provided (gasIncluded case), use the quote's gas fees
|
|
646
|
-
// Convert to hex since txFee values from the quote are decimal strings
|
|
647
|
-
if (txFee) {
|
|
648
|
-
return {
|
|
649
|
-
maxFeePerGas: toHex(txFee.maxFeePerGas),
|
|
650
|
-
maxPriorityFeePerGas: toHex(txFee.maxPriorityFeePerGas),
|
|
651
|
-
gas: gas ? toHex(gas) : undefined,
|
|
652
|
-
};
|
|
653
|
-
}
|
|
654
|
-
const { gasFeeEstimates } = this.messenger.call('GasFeeController:getState');
|
|
655
|
-
const { estimates: txGasFeeEstimates } = await __classPrivateFieldGet(this, _BridgeStatusController_estimateGasFeeFn, "f").call(this, {
|
|
656
|
-
transactionParams,
|
|
657
|
-
chainId,
|
|
658
|
-
networkClientId,
|
|
659
|
-
});
|
|
660
|
-
const { maxFeePerGas, maxPriorityFeePerGas } = getTxGasEstimates({
|
|
661
|
-
networkGasFeeEstimates: gasFeeEstimates,
|
|
662
|
-
txGasFeeEstimates,
|
|
663
|
-
});
|
|
664
|
-
return {
|
|
665
|
-
maxFeePerGas,
|
|
666
|
-
maxPriorityFeePerGas,
|
|
667
|
-
gas: gas ? toHex(gas) : undefined,
|
|
668
|
-
};
|
|
669
|
-
});
|
|
479
|
+
// TODO simplify and make more readable
|
|
670
480
|
/**
|
|
671
481
|
* Submits batched EVM transactions to the TransactionController
|
|
672
482
|
*
|
|
@@ -682,26 +492,9 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
682
492
|
_BridgeStatusController_handleEvmTransactionBatch.set(this, async (args) => {
|
|
683
493
|
const transactionParams = await getAddTransactionBatchParams({
|
|
684
494
|
messenger: this.messenger,
|
|
685
|
-
estimateGasFeeFn: __classPrivateFieldGet(this, _BridgeStatusController_estimateGasFeeFn, "f"),
|
|
686
495
|
...args,
|
|
687
496
|
});
|
|
688
|
-
|
|
689
|
-
[TransactionType.bridgeApproval]: transactionParams.transactions.find(({ type }) => type === TransactionType.bridgeApproval)?.params.data,
|
|
690
|
-
[TransactionType.swapApproval]: transactionParams.transactions.find(({ type }) => type === TransactionType.swapApproval)?.params.data,
|
|
691
|
-
[TransactionType.bridge]: transactionParams.transactions.find(({ type }) => type === TransactionType.bridge)?.params.data,
|
|
692
|
-
[TransactionType.swap]: transactionParams.transactions.find(({ type }) => type === TransactionType.swap)?.params.data,
|
|
693
|
-
};
|
|
694
|
-
const { batchId } = await __classPrivateFieldGet(this, _BridgeStatusController_addTransactionBatchFn, "f").call(this, transactionParams);
|
|
695
|
-
const { approvalMeta, tradeMeta } = findAndUpdateTransactionsInBatch({
|
|
696
|
-
messenger: this.messenger,
|
|
697
|
-
updateTransactionFn: __classPrivateFieldGet(this, _BridgeStatusController_updateTransactionFn, "f"),
|
|
698
|
-
batchId,
|
|
699
|
-
txDataByType,
|
|
700
|
-
});
|
|
701
|
-
if (!tradeMeta) {
|
|
702
|
-
throw new Error('Failed to update cross-chain swap transaction batch: tradeMeta not found');
|
|
703
|
-
}
|
|
704
|
-
return { approvalMeta, tradeMeta };
|
|
497
|
+
return await addTransactionBatch(this.messenger, __classPrivateFieldGet(this, _BridgeStatusController_addTransactionBatchFn, "f"), transactionParams);
|
|
705
498
|
});
|
|
706
499
|
/**
|
|
707
500
|
* Submits a cross-chain swap transaction
|
|
@@ -716,11 +509,8 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
716
509
|
* @returns The transaction meta
|
|
717
510
|
*/
|
|
718
511
|
this.submitTx = async (accountAddress, quoteResponse, isStxEnabledOnClient, quotesReceivedContext, location = MetaMetricsSwapsEventSource.MainView, abTests, activeAbTests) => {
|
|
719
|
-
this.messenger
|
|
720
|
-
|
|
721
|
-
// If the trade has a featureId, it means it was submitted outside of the Unified Swap and Bridge experience, so no QuotesReceived event is published
|
|
722
|
-
quoteResponse.featureId ? undefined : quotesReceivedContext);
|
|
723
|
-
const selectedAccount = __classPrivateFieldGet(this, _BridgeStatusController_instances, "m", _BridgeStatusController_getMultichainSelectedAccount).call(this, accountAddress);
|
|
512
|
+
stopPollingForQuotes(this.messenger, quoteResponse.featureId, quotesReceivedContext);
|
|
513
|
+
const selectedAccount = getAccountByAddress(this.messenger, accountAddress);
|
|
724
514
|
if (!selectedAccount) {
|
|
725
515
|
throw new Error('Failed to submit cross-chain swap transaction: undefined multichain account');
|
|
726
516
|
}
|
|
@@ -739,19 +529,11 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
739
529
|
if (isNonEvmChainId(quoteResponse.quote.srcChainId)) {
|
|
740
530
|
// Handle non-EVM approval if present (e.g., Tron token approvals)
|
|
741
531
|
if (quoteResponse.approval && isTronTrade(quoteResponse.approval)) {
|
|
742
|
-
const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, {
|
|
743
|
-
name: isBridgeTx
|
|
744
|
-
? TraceName.BridgeTransactionApprovalCompleted
|
|
745
|
-
: TraceName.SwapTransactionApprovalCompleted,
|
|
746
|
-
data: {
|
|
747
|
-
srcChainId: formatChainIdToCaip(quoteResponse.quote.srcChainId),
|
|
748
|
-
stxEnabled: false,
|
|
749
|
-
},
|
|
750
|
-
}, async () => {
|
|
532
|
+
const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, getApprovalTraceParams(quoteResponse, false), async () => {
|
|
751
533
|
try {
|
|
752
534
|
return quoteResponse.approval &&
|
|
753
535
|
isTronTrade(quoteResponse.approval)
|
|
754
|
-
? await
|
|
536
|
+
? await handleNonEvmTx(this.messenger, quoteResponse.approval, quoteResponse, selectedAccount)
|
|
755
537
|
: /* c8 ignore start */
|
|
756
538
|
undefined;
|
|
757
539
|
/* c8 ignore end */
|
|
@@ -769,22 +551,14 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
769
551
|
// Add delay after approval similar to EVM flow
|
|
770
552
|
await handleApprovalDelay(quoteResponse.quote.srcChainId);
|
|
771
553
|
}
|
|
772
|
-
txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, {
|
|
773
|
-
name: isBridgeTx
|
|
774
|
-
? TraceName.BridgeTransactionCompleted
|
|
775
|
-
: TraceName.SwapTransactionCompleted,
|
|
776
|
-
data: {
|
|
777
|
-
srcChainId: formatChainIdToCaip(quoteResponse.quote.srcChainId),
|
|
778
|
-
stxEnabled: false,
|
|
779
|
-
},
|
|
780
|
-
}, async () => {
|
|
554
|
+
txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, getTraceParams(quoteResponse, false), async () => {
|
|
781
555
|
try {
|
|
782
556
|
if (!(isTronTrade(quoteResponse.trade) ||
|
|
783
557
|
isBitcoinTrade(quoteResponse.trade) ||
|
|
784
558
|
typeof quoteResponse.trade === 'string')) {
|
|
785
559
|
throw new Error('Failed to submit cross-chain swap transaction: trade is not a non-EVM transaction');
|
|
786
560
|
}
|
|
787
|
-
return await
|
|
561
|
+
return await handleNonEvmTx(this.messenger, quoteResponse.trade, quoteResponse, selectedAccount);
|
|
788
562
|
}
|
|
789
563
|
catch (error) {
|
|
790
564
|
!quoteResponse.featureId &&
|
|
@@ -802,15 +576,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
802
576
|
// Extension does not have this issue
|
|
803
577
|
const requireApproval = __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === BridgeClientId.MOBILE && isHardwareAccount;
|
|
804
578
|
// Handle smart transactions if enabled
|
|
805
|
-
txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, {
|
|
806
|
-
name: isBridgeTx
|
|
807
|
-
? TraceName.BridgeTransactionCompleted
|
|
808
|
-
: TraceName.SwapTransactionCompleted,
|
|
809
|
-
data: {
|
|
810
|
-
srcChainId: formatChainIdToCaip(quoteResponse.quote.srcChainId),
|
|
811
|
-
stxEnabled: isStxEnabledOnClient,
|
|
812
|
-
},
|
|
813
|
-
}, async () => {
|
|
579
|
+
txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_trace, "f").call(this, getTraceParams(quoteResponse, isStxEnabledOnClient), async () => {
|
|
814
580
|
if (!isEvmTxData(quoteResponse.trade)) {
|
|
815
581
|
throw new Error('Failed to submit cross-chain swap transaction: trade is not an EVM transaction');
|
|
816
582
|
}
|
|
@@ -818,18 +584,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
818
584
|
// Delegated accounts only allow 1 in-flight tx, so approve + swap
|
|
819
585
|
// must be batched into a single transaction
|
|
820
586
|
const hexChainId = formatChainIdToHex(quoteResponse.quote.srcChainId);
|
|
821
|
-
isDelegatedAccount = await (
|
|
822
|
-
try {
|
|
823
|
-
const atomicBatchSupport = await this.messenger.call('TransactionController:isAtomicBatchSupported', {
|
|
824
|
-
address: quoteResponse.trade.from,
|
|
825
|
-
chainIds: [hexChainId],
|
|
826
|
-
});
|
|
827
|
-
return atomicBatchSupport.some((entry) => entry.isSupported && entry.delegationAddress);
|
|
828
|
-
}
|
|
829
|
-
catch {
|
|
830
|
-
return false;
|
|
831
|
-
}
|
|
832
|
-
})();
|
|
587
|
+
isDelegatedAccount = await checkIsDelegatedAccount(this.messenger, quoteResponse.trade.from, [hexChainId]);
|
|
833
588
|
if (isStxEnabledOnClient ||
|
|
834
589
|
quoteResponse.quote.gasIncluded7702 ||
|
|
835
590
|
isDelegatedAccount) {
|
|
@@ -848,21 +603,25 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
848
603
|
return tradeMeta;
|
|
849
604
|
}
|
|
850
605
|
// Set approval time and id if an approval tx is needed
|
|
851
|
-
const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleApprovalTx, "f").call(this, isBridgeTx, quoteResponse.quote.srcChainId, quoteResponse.approval && isEvmTxData(quoteResponse.approval)
|
|
606
|
+
const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleApprovalTx, "f").call(this, quoteResponse, isBridgeTx, quoteResponse.quote.srcChainId, quoteResponse.approval && isEvmTxData(quoteResponse.approval)
|
|
852
607
|
? quoteResponse.approval
|
|
853
608
|
: undefined, quoteResponse.resetApproval, requireApproval);
|
|
854
609
|
approvalTxId = approvalTxMeta?.id;
|
|
855
|
-
|
|
610
|
+
// Hardware-wallet delay first (Ledger second-prompt spacing), then wait for
|
|
611
|
+
// on-chain approval confirmation so swap gas estimation runs after allowance is set.
|
|
612
|
+
if (requireApproval && approvalTxMeta) {
|
|
613
|
+
await handleMobileHardwareWalletDelay(requireApproval);
|
|
614
|
+
await waitForTxConfirmation(this.messenger, approvalTxMeta.id);
|
|
615
|
+
}
|
|
616
|
+
else {
|
|
617
|
+
await handleMobileHardwareWalletDelay(requireApproval);
|
|
618
|
+
}
|
|
856
619
|
// Generate actionId for pre-submission history (non-batch EVM only)
|
|
857
620
|
const actionId = generateActionId().toString();
|
|
858
621
|
// Add pre-submission history keyed by actionId
|
|
859
622
|
// This ensures we have quote data available if transaction fails during submission
|
|
860
623
|
__classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
|
|
861
624
|
accountAddress: selectedAccount.address,
|
|
862
|
-
statusRequest: {
|
|
863
|
-
...getStatusRequestParams(quoteResponse),
|
|
864
|
-
srcTxHash: '', // Not available yet
|
|
865
|
-
},
|
|
866
625
|
quoteResponse,
|
|
867
626
|
slippagePercentage: 0,
|
|
868
627
|
isStxEnabled: isStxEnabledOnClient,
|
|
@@ -871,10 +630,12 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
871
630
|
location,
|
|
872
631
|
abTests,
|
|
873
632
|
activeAbTests,
|
|
874
|
-
|
|
633
|
+
actionId,
|
|
634
|
+
});
|
|
875
635
|
// Pass txFee when gasIncluded is true to use the quote's gas fees
|
|
876
636
|
// instead of re-estimating (which would fail for max native token swaps)
|
|
877
|
-
const tradeTxMeta = await
|
|
637
|
+
const tradeTxMeta = await submitEvmTransaction({
|
|
638
|
+
messenger: this.messenger,
|
|
878
639
|
transactionType: isBridgeTx
|
|
879
640
|
? TransactionType.bridge
|
|
880
641
|
: TransactionType.swap,
|
|
@@ -902,10 +663,6 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
902
663
|
__classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
|
|
903
664
|
accountAddress: selectedAccount.address,
|
|
904
665
|
bridgeTxMeta: txMeta, // Only the id field is used by the BridgeStatusController
|
|
905
|
-
statusRequest: {
|
|
906
|
-
...getStatusRequestParams(quoteResponse),
|
|
907
|
-
srcTxHash: txMeta.hash,
|
|
908
|
-
},
|
|
909
666
|
quoteResponse,
|
|
910
667
|
slippagePercentage: 0, // TODO include slippage provided by quote if using dynamic slippage, or slippage from quote request
|
|
911
668
|
isStxEnabled: isStxEnabledOnClient,
|
|
@@ -944,9 +701,11 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
944
701
|
*/
|
|
945
702
|
this.submitIntent = async (params) => {
|
|
946
703
|
const { quoteResponse, accountAddress, location, abTests, activeAbTests } = params;
|
|
947
|
-
|
|
704
|
+
// TODO add metrics context
|
|
705
|
+
stopPollingForQuotes(this.messenger);
|
|
706
|
+
const startTime = Date.now();
|
|
948
707
|
// Build pre-confirmation properties for error tracking parity with submitTx
|
|
949
|
-
const account =
|
|
708
|
+
const account = getAccountByAddress(this.messenger, accountAddress);
|
|
950
709
|
const isHardwareAccount = Boolean(account) && isHardwareWallet(account);
|
|
951
710
|
const preConfirmationProperties = getPreConfirmationPropertiesFromQuote(quoteResponse, false, isHardwareAccount, location, abTests, activeAbTests);
|
|
952
711
|
try {
|
|
@@ -956,16 +715,17 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
956
715
|
const isBridgeTx = isCrossChain(quoteResponse.quote.srcChainId, quoteResponse.quote.destChainId);
|
|
957
716
|
const requireApproval = isHardwareAccount && __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f") === BridgeClientId.MOBILE;
|
|
958
717
|
// Handle approval silently for better UX in intent flows
|
|
959
|
-
const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleApprovalTx, "f").call(this, isBridgeTx, quoteResponse.quote.srcChainId, quoteResponse.approval, quoteResponse.resetApproval, requireApproval);
|
|
718
|
+
const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleApprovalTx, "f").call(this, quoteResponse, isBridgeTx, quoteResponse.quote.srcChainId, quoteResponse.approval, quoteResponse.resetApproval, requireApproval);
|
|
960
719
|
const approvalTxId = approvalTxMeta?.id;
|
|
961
720
|
if (approvalTxId) {
|
|
962
|
-
await
|
|
721
|
+
await waitForTxConfirmation(this.messenger, approvalTxId);
|
|
963
722
|
}
|
|
964
723
|
const { srcChainId, requestId } = quoteResponse.quote;
|
|
965
|
-
const signature = await
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
724
|
+
const signature = await signTypedMessage({
|
|
725
|
+
messenger: this.messenger,
|
|
726
|
+
accountAddress,
|
|
727
|
+
typedData: intent.typedData,
|
|
728
|
+
});
|
|
969
729
|
const submissionParams = {
|
|
970
730
|
srcChainId,
|
|
971
731
|
quoteId: requestId,
|
|
@@ -974,8 +734,13 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
974
734
|
userAddress: accountAddress,
|
|
975
735
|
aggregatorId: intent.protocol,
|
|
976
736
|
};
|
|
977
|
-
const
|
|
978
|
-
|
|
737
|
+
const { id: orderUid, status } = await postSubmitOrder({
|
|
738
|
+
params: submissionParams,
|
|
739
|
+
clientId: __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f"),
|
|
740
|
+
jwt: await getJwt(this.messenger),
|
|
741
|
+
fetchFn: __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"),
|
|
742
|
+
bridgeApiBaseUrl: __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl,
|
|
743
|
+
});
|
|
979
744
|
// Determine transaction type: swap for same-chain, bridge for cross-chain
|
|
980
745
|
const transactionType = isBridgeTx
|
|
981
746
|
? /* c8 ignore start */
|
|
@@ -983,7 +748,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
983
748
|
: /* c8 ignore end */
|
|
984
749
|
TransactionType.swap;
|
|
985
750
|
// Create actual transaction in Transaction Controller first
|
|
986
|
-
const networkClientId = this.messenger
|
|
751
|
+
const networkClientId = getNetworkClientIdByChainId(this.messenger, srcChainId);
|
|
987
752
|
// This is a synthetic transaction whose purpose is to be able
|
|
988
753
|
// to track the order status via the history
|
|
989
754
|
const intentTransactionParams = {
|
|
@@ -996,25 +761,16 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
996
761
|
gas: '0x5208', // Minimal gas for display purposes
|
|
997
762
|
gasPrice: '0x3b9aca00', // 1 Gwei - will be converted to EIP-1559 fees if network supports it
|
|
998
763
|
};
|
|
999
|
-
const
|
|
1000
|
-
origin: 'metamask',
|
|
1001
|
-
actionId: generateActionId(),
|
|
764
|
+
const initialTxMeta = await addSyntheticTransaction(this.messenger, intentTransactionParams, {
|
|
1002
765
|
requireApproval: false,
|
|
1003
|
-
isStateOnly: true,
|
|
1004
766
|
networkClientId,
|
|
1005
767
|
type: transactionType,
|
|
1006
768
|
});
|
|
1007
|
-
|
|
1008
|
-
// Map intent order status to TransactionController status
|
|
1009
|
-
const initialTransactionStatus = mapIntentOrderStatusToTransactionStatus(intentOrder.status);
|
|
1010
|
-
// Update transaction with proper initial status based on intent order
|
|
1011
|
-
const statusUpdatedTxMeta = {
|
|
1012
|
-
...intentTxMeta,
|
|
1013
|
-
status: initialTransactionStatus,
|
|
1014
|
-
};
|
|
1015
|
-
// Update with actual transaction metadata
|
|
769
|
+
// Update txHistory with actual transaction metadata
|
|
1016
770
|
const syntheticMeta = {
|
|
1017
|
-
...
|
|
771
|
+
...initialTxMeta,
|
|
772
|
+
// Map intent order status to TransactionController status
|
|
773
|
+
status: mapIntentOrderStatusToTransactionStatus(status),
|
|
1018
774
|
isIntentTx: true,
|
|
1019
775
|
orderUid,
|
|
1020
776
|
};
|
|
@@ -1028,14 +784,9 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
1028
784
|
id: bridgeHistoryKey,
|
|
1029
785
|
originalTransactionId: syntheticMeta.id, // Keep original txId for TransactionController updates
|
|
1030
786
|
};
|
|
1031
|
-
const startTime = Date.now();
|
|
1032
787
|
__classPrivateFieldGet(this, _BridgeStatusController_addTxToHistory, "f").call(this, {
|
|
1033
788
|
accountAddress,
|
|
1034
789
|
bridgeTxMeta: bridgeTxMetaForHistory,
|
|
1035
|
-
statusRequest: {
|
|
1036
|
-
...getStatusRequestParams(quoteResponse),
|
|
1037
|
-
srcTxHash: syntheticMeta.hash ?? '',
|
|
1038
|
-
},
|
|
1039
790
|
quoteResponse,
|
|
1040
791
|
slippagePercentage: 0,
|
|
1041
792
|
isStxEnabled: false,
|
|
@@ -1096,35 +847,48 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
1096
847
|
};
|
|
1097
848
|
// This will publish events for PERPS dropped tx failures as well
|
|
1098
849
|
if (!txMetaId) {
|
|
1099
|
-
|
|
850
|
+
trackMetricsEvent({
|
|
851
|
+
messenger: this.messenger,
|
|
852
|
+
eventName,
|
|
853
|
+
properties: baseProperties,
|
|
854
|
+
});
|
|
1100
855
|
return;
|
|
1101
856
|
}
|
|
1102
857
|
const historyItem = this.state.txHistory[txMetaId];
|
|
1103
858
|
if (!historyItem) {
|
|
1104
|
-
|
|
859
|
+
trackMetricsEvent({
|
|
860
|
+
messenger: this.messenger,
|
|
861
|
+
eventName,
|
|
862
|
+
properties: baseProperties,
|
|
863
|
+
});
|
|
1105
864
|
return;
|
|
1106
865
|
}
|
|
866
|
+
const { featureId, approvalTxId, quote } = historyItem;
|
|
1107
867
|
const requestParamProperties = getRequestParamFromHistory(historyItem);
|
|
1108
868
|
// Always publish StatusValidationFailed event, regardless of featureId
|
|
1109
869
|
if (eventName === UnifiedSwapBridgeEventName.StatusValidationFailed) {
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
870
|
+
trackMetricsEvent({
|
|
871
|
+
messenger: this.messenger,
|
|
872
|
+
eventName,
|
|
873
|
+
properties: {
|
|
874
|
+
...baseProperties,
|
|
875
|
+
chain_id_source: requestParamProperties.chain_id_source,
|
|
876
|
+
chain_id_destination: requestParamProperties.chain_id_destination,
|
|
877
|
+
token_address_source: requestParamProperties.token_address_source,
|
|
878
|
+
token_address_destination: requestParamProperties.token_address_destination,
|
|
879
|
+
refresh_count: historyItem.attempts?.counter ?? 0,
|
|
880
|
+
},
|
|
1117
881
|
});
|
|
1118
882
|
return;
|
|
1119
883
|
}
|
|
1120
884
|
// Skip tracking all other events when featureId is set (i.e. PERPS)
|
|
1121
|
-
if (
|
|
885
|
+
if (featureId) {
|
|
1122
886
|
return;
|
|
1123
887
|
}
|
|
1124
|
-
const selectedAccount = this.messenger
|
|
1125
|
-
const
|
|
1126
|
-
const txMeta = transactions
|
|
1127
|
-
const approvalTxMeta = transactions
|
|
888
|
+
const selectedAccount = getAccountByAddress(this.messenger, historyItem.account);
|
|
889
|
+
const transactions = getTransactions(this.messenger);
|
|
890
|
+
const txMeta = transactions.find((tx) => tx.id === txMetaId);
|
|
891
|
+
const approvalTxMeta = transactions.find((tx) => tx.id === approvalTxId);
|
|
1128
892
|
const requiredEventProperties = {
|
|
1129
893
|
...baseProperties,
|
|
1130
894
|
...requestParamProperties,
|
|
@@ -1132,26 +896,25 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
1132
896
|
...getTradeDataFromHistory(historyItem),
|
|
1133
897
|
...getTxStatusesFromHistory(historyItem),
|
|
1134
898
|
...getFinalizedTxProperties(historyItem, txMeta, approvalTxMeta),
|
|
1135
|
-
...getPriceImpactFromQuote(
|
|
899
|
+
...getPriceImpactFromQuote(quote),
|
|
1136
900
|
};
|
|
1137
|
-
|
|
901
|
+
trackMetricsEvent({
|
|
902
|
+
messenger: this.messenger,
|
|
903
|
+
eventName,
|
|
904
|
+
properties: requiredEventProperties,
|
|
905
|
+
});
|
|
1138
906
|
});
|
|
1139
907
|
__classPrivateFieldSet(this, _BridgeStatusController_clientId, clientId, "f");
|
|
1140
908
|
__classPrivateFieldSet(this, _BridgeStatusController_fetchFn, fetchFn, "f");
|
|
1141
|
-
__classPrivateFieldSet(this, _BridgeStatusController_addTransactionFn, addTransactionFn, "f");
|
|
1142
909
|
__classPrivateFieldSet(this, _BridgeStatusController_addTransactionBatchFn, addTransactionBatchFn, "f");
|
|
1143
|
-
__classPrivateFieldSet(this, _BridgeStatusController_updateTransactionFn, updateTransactionFn, "f");
|
|
1144
|
-
__classPrivateFieldSet(this, _BridgeStatusController_estimateGasFeeFn, estimateGasFeeFn, "f");
|
|
1145
910
|
__classPrivateFieldSet(this, _BridgeStatusController_config, {
|
|
1146
911
|
customBridgeApiBaseUrl: config?.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,
|
|
1147
912
|
}, "f");
|
|
1148
913
|
__classPrivateFieldSet(this, _BridgeStatusController_trace, traceFn ?? ((_request, fn) => fn?.()), "f");
|
|
1149
914
|
__classPrivateFieldSet(this, _BridgeStatusController_intentManager, new IntentManager({
|
|
1150
915
|
messenger: this.messenger,
|
|
1151
|
-
updateTransactionFn: __classPrivateFieldGet(this, _BridgeStatusController_updateTransactionFn, "f"),
|
|
1152
916
|
customBridgeApiBaseUrl: __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl,
|
|
1153
917
|
fetchFn: __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"),
|
|
1154
|
-
getJwt: __classPrivateFieldGet(this, _BridgeStatusController_getJwt, "f"),
|
|
1155
918
|
}), "f");
|
|
1156
919
|
// Register action handlers
|
|
1157
920
|
this.messenger.registerActionHandler(`${BRIDGE_STATUS_CONTROLLER_NAME}:startPollingForBridgeTxStatus`, this.startPollingForBridgeTxStatus.bind(this));
|
|
@@ -1208,7 +971,5 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
|
1208
971
|
__classPrivateFieldGet(this, _BridgeStatusController_restartPollingForIncompleteHistoryItems, "f").call(this);
|
|
1209
972
|
}
|
|
1210
973
|
}
|
|
1211
|
-
_BridgeStatusController_pollingTokensByTxMetaId = new WeakMap(), _BridgeStatusController_intentManager = new WeakMap(), _BridgeStatusController_clientId = new WeakMap(), _BridgeStatusController_fetchFn = new WeakMap(), _BridgeStatusController_config = new WeakMap(),
|
|
1212
|
-
return this.messenger.call('AccountsController:getAccountByAddress', accountAddress);
|
|
1213
|
-
};
|
|
974
|
+
_BridgeStatusController_pollingTokensByTxMetaId = new WeakMap(), _BridgeStatusController_intentManager = new WeakMap(), _BridgeStatusController_clientId = new WeakMap(), _BridgeStatusController_fetchFn = new WeakMap(), _BridgeStatusController_config = new WeakMap(), _BridgeStatusController_addTransactionBatchFn = new WeakMap(), _BridgeStatusController_trace = new WeakMap(), _BridgeStatusController_markTxAsFailed = new WeakMap(), _BridgeStatusController_restartPollingForIncompleteHistoryItems = new WeakMap(), _BridgeStatusController_addTxToHistory = new WeakMap(), _BridgeStatusController_rekeyHistoryItem = 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_handleApprovalTx = new WeakMap(), _BridgeStatusController_handleEvmTransactionBatch = new WeakMap(), _BridgeStatusController_trackUnifiedSwapBridgeEvent = new WeakMap();
|
|
1214
975
|
//# sourceMappingURL=bridge-status-controller.mjs.map
|