@metamask-previews/bridge-status-controller 12.0.1-preview-c555b24d → 12.0.1-preview-23d1c73f
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 +14 -0
- package/dist/bridge-status-controller.cjs +301 -6
- package/dist/bridge-status-controller.cjs.map +1 -1
- package/dist/bridge-status-controller.d.cts +25 -4
- package/dist/bridge-status-controller.d.cts.map +1 -1
- package/dist/bridge-status-controller.d.mts +25 -4
- package/dist/bridge-status-controller.d.mts.map +1 -1
- package/dist/bridge-status-controller.mjs +304 -9
- package/dist/bridge-status-controller.mjs.map +1 -1
- package/dist/constants.cjs +3 -1
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +2 -0
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.mts +2 -0
- package/dist/constants.d.mts.map +1 -1
- package/dist/constants.mjs +2 -0
- package/dist/constants.mjs.map +1 -1
- package/dist/index.cjs +4 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs +10 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +18 -7
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +18 -7
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs +9 -0
- package/dist/types.mjs.map +1 -1
- package/dist/utils/bridge-status.cjs +6 -5
- package/dist/utils/bridge-status.cjs.map +1 -1
- package/dist/utils/bridge-status.d.cts.map +1 -1
- package/dist/utils/bridge-status.d.mts.map +1 -1
- package/dist/utils/bridge-status.mjs +6 -5
- package/dist/utils/bridge-status.mjs.map +1 -1
- package/dist/utils/gas.cjs +23 -0
- package/dist/utils/gas.cjs.map +1 -0
- package/dist/utils/gas.d.cts +12 -0
- package/dist/utils/gas.d.cts.map +1 -0
- package/dist/utils/gas.d.mts +12 -0
- package/dist/utils/gas.d.mts.map +1 -0
- package/dist/utils/gas.mjs +19 -0
- package/dist/utils/gas.mjs.map +1 -0
- package/dist/utils/smart-transactions.cjs +13 -0
- package/dist/utils/smart-transactions.cjs.map +1 -0
- package/dist/utils/smart-transactions.d.cts +3 -0
- package/dist/utils/smart-transactions.d.cts.map +1 -0
- package/dist/utils/smart-transactions.d.mts +3 -0
- package/dist/utils/smart-transactions.d.mts.map +1 -0
- package/dist/utils/smart-transactions.mjs +9 -0
- package/dist/utils/smart-transactions.mjs.map +1 -0
- package/dist/utils/transaction.cjs +78 -0
- package/dist/utils/transaction.cjs.map +1 -0
- package/dist/utils/transaction.d.cts +31 -0
- package/dist/utils/transaction.d.cts.map +1 -0
- package/dist/utils/transaction.d.mts +31 -0
- package/dist/utils/transaction.d.mts.map +1 -0
- package/dist/utils/transaction.mjs +71 -0
- package/dist/utils/transaction.mjs.map +1 -0
- package/dist/utils/validators.cjs +1 -1
- package/dist/utils/validators.cjs.map +1 -1
- package/dist/utils/validators.mjs +2 -2
- package/dist/utils/validators.mjs.map +1 -1
- package/package.json +19 -3
@@ -1,7 +1,11 @@
|
|
1
|
-
import type
|
1
|
+
import { type QuoteResponse } from "@metamask/bridge-controller";
|
2
|
+
import type { QuoteMetadata, TxData } from "@metamask/bridge-controller";
|
3
|
+
import type { TransactionController } from "@metamask/transaction-controller";
|
4
|
+
import { type TransactionMeta } from "@metamask/transaction-controller";
|
5
|
+
import type { UserOperationController } from "@metamask/user-operation-controller";
|
2
6
|
import { BRIDGE_STATUS_CONTROLLER_NAME } from "./constants.mjs";
|
3
7
|
import { type BridgeStatusControllerMessenger } from "./types.mjs";
|
4
|
-
import type { BridgeStatusControllerState, StartPollingForBridgeTxStatusArgsSerialized, FetchFunction } from "./types.mjs";
|
8
|
+
import type { BridgeStatusControllerState, StartPollingForBridgeTxStatusArgsSerialized, FetchFunction, BridgeClientId } from "./types.mjs";
|
5
9
|
/** The input to start polling for the {@link BridgeStatusController} */
|
6
10
|
type BridgeStatusPollingInput = FetchBridgeTxStatusArgs;
|
7
11
|
export type FetchBridgeTxStatusArgs = {
|
@@ -24,20 +28,37 @@ declare const BridgeStatusController_base: (abstract new (...args: any[]) => {
|
|
24
28
|
}) & typeof import("@metamask/base-controller").BaseController;
|
25
29
|
export declare class BridgeStatusController extends BridgeStatusController_base<typeof BRIDGE_STATUS_CONTROLLER_NAME, BridgeStatusControllerState, BridgeStatusControllerMessenger> {
|
26
30
|
#private;
|
27
|
-
constructor({ messenger, state, clientId, fetchFn, config, }: {
|
31
|
+
constructor({ messenger, state, clientId, fetchFn, addTransactionFn, addUserOperationFromTransactionFn, estimateGasFeeFn, config, }: {
|
28
32
|
messenger: BridgeStatusControllerMessenger;
|
29
33
|
state?: Partial<BridgeStatusControllerState>;
|
30
34
|
clientId: BridgeClientId;
|
31
35
|
fetchFn: FetchFunction;
|
32
|
-
|
36
|
+
addTransactionFn: typeof TransactionController.prototype.addTransaction;
|
37
|
+
estimateGasFeeFn: typeof TransactionController.prototype.estimateGasFee;
|
38
|
+
addUserOperationFromTransactionFn: typeof UserOperationController.prototype.addUserOperationFromTransaction;
|
39
|
+
config: {
|
33
40
|
customBridgeApiBaseUrl?: string;
|
41
|
+
smartTransactionsEnabledByDefault: boolean;
|
34
42
|
};
|
35
43
|
});
|
44
|
+
/**
|
45
|
+
* Submits a cross-chain swap transaction
|
46
|
+
*
|
47
|
+
* @param quoteResponse - The quote response
|
48
|
+
* @param isStxEnabledOnClient - Whether smart transactions are enabled on the client
|
49
|
+
* @returns The transaction meta
|
50
|
+
*/
|
51
|
+
submitTx: (quoteResponse: QuoteResponse<TxData | string> & QuoteMetadata, isStxEnabledOnClient: boolean) => Promise<TransactionMeta>;
|
36
52
|
resetState: () => void;
|
37
53
|
wipeBridgeStatus: ({ address, ignoreNetwork, }: {
|
38
54
|
address: string;
|
39
55
|
ignoreNetwork: boolean;
|
40
56
|
}) => void;
|
57
|
+
/**
|
58
|
+
* Starts polling for the bridge tx status
|
59
|
+
*
|
60
|
+
* @param startPollingForBridgeTxStatusArgs - The args to start polling for the bridge tx status
|
61
|
+
*/
|
41
62
|
startPollingForBridgeTxStatus: (startPollingForBridgeTxStatusArgs: StartPollingForBridgeTxStatusArgsSerialized) => void;
|
42
63
|
_executePoll: (pollingInput: BridgeStatusPollingInput) => Promise<void>;
|
43
64
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"bridge-status-controller.d.mts","sourceRoot":"","sources":["../src/bridge-status-controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,
|
1
|
+
{"version":3,"file":"bridge-status-controller.d.mts","sourceRoot":"","sources":["../src/bridge-status-controller.ts"],"names":[],"mappings":"AACA,OAAO,EAOL,KAAK,aAAa,EACnB,oCAAoC;AACrC,OAAO,KAAK,EAEV,aAAa,EACb,MAAM,EACP,oCAAoC;AAIrC,OAAO,KAAK,EACV,qBAAqB,EAEtB,yCAAyC;AAC1C,OAAO,EAEL,KAAK,eAAe,EACrB,yCAAyC;AAC1C,OAAO,KAAK,EAAE,uBAAuB,EAAE,4CAA4C;AAKnF,OAAO,EAEL,6BAA6B,EAI9B,wBAAoB;AACrB,OAAO,EAAe,KAAK,+BAA+B,EAAE,oBAAgB;AAC5E,OAAO,KAAK,EACV,2BAA2B,EAC3B,2CAA2C,EAC3C,aAAa,EACb,cAAc,EACf,oBAAgB;AAsBjB,wEAAwE;AACxE,KAAK,wBAAwB,GAAG,uBAAuB,CAAC;AAGxD,MAAM,MAAM,uBAAuB,GAAG;IACpC,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;;;;;;;;;;;;;;;;AACF,qBAAa,sBAAuB,SAAQ,4BAC1C,OAAO,6BAA6B,EACpC,2BAA2B,EAC3B,+BAA+B,CAChC;;gBAkBa,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,OAAO,EACP,gBAAgB,EAChB,iCAAiC,EACjC,gBAAgB,EAChB,MAAM,GACP,EAAE;QACD,SAAS,EAAE,+BAA+B,CAAC;QAC3C,KAAK,CAAC,EAAE,OAAO,CAAC,2BAA2B,CAAC,CAAC;QAC7C,QAAQ,EAAE,cAAc,CAAC;QACzB,OAAO,EAAE,aAAa,CAAC;QACvB,gBAAgB,EAAE,OAAO,qBAAqB,CAAC,SAAS,CAAC,cAAc,CAAC;QACxE,gBAAgB,EAAE,OAAO,qBAAqB,CAAC,SAAS,CAAC,cAAc,CAAC;QACxE,iCAAiC,EAAE,OAAO,uBAAuB,CAAC,SAAS,CAAC,+BAA+B,CAAC;QAC5G,MAAM,EAAE;YACN,sBAAsB,CAAC,EAAE,MAAM,CAAC;YAChC,iCAAiC,EAAE,OAAO,CAAC;SAC5C,CAAC;KACH;IAuHD;;;;;;OAMG;IACH,QAAQ,kBACS,cAAc,MAAM,GAAG,MAAM,CAAC,GAAG,aAAa,wBACvC,OAAO,8BA0E7B;IAEF,UAAU,aAIR;IAEF,gBAAgB;iBAIL,MAAM;uBACA,OAAO;eAmBtB;IA8BF;;;;OAIG;IACH,6BAA6B,sCACQ,2CAA2C,UAiD9E;IAIF,YAAY,iBAAwB,wBAAwB,mBAE1D;CA0ZH"}
|
@@ -9,13 +9,21 @@ 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 _BridgeStatusController_instances, _BridgeStatusController_pollingTokensByTxMetaId, _BridgeStatusController_clientId, _BridgeStatusController_fetchFn, _BridgeStatusController_config, _BridgeStatusController_restartPollingForIncompleteHistoryItems, _BridgeStatusController_getMultichainSelectedAccountAddress, _BridgeStatusController_fetchBridgeTxStatus, _BridgeStatusController_getSrcTxHash, _BridgeStatusController_updateSrcTxHash, _BridgeStatusController_wipeBridgeStatusByChainId;
|
13
|
-
import {
|
12
|
+
var _BridgeStatusController_instances, _BridgeStatusController_pollingTokensByTxMetaId, _BridgeStatusController_clientId, _BridgeStatusController_fetchFn, _BridgeStatusController_config, _BridgeStatusController_addTransactionFn, _BridgeStatusController_addUserOperationFromTransactionFn, _BridgeStatusController_estimateGasFeeFn, _BridgeStatusController_handleUSDTAllowanceReset, _BridgeStatusController_handleLineaDelay, _BridgeStatusController_calculateGasFees, _BridgeStatusController_restartPollingForIncompleteHistoryItems, _BridgeStatusController_getMultichainSelectedAccount, _BridgeStatusController_getMultichainSelectedAccountAddress, _BridgeStatusController_fetchBridgeTxStatus, _BridgeStatusController_getSrcTxHash, _BridgeStatusController_updateSrcTxHash, _BridgeStatusController_wipeBridgeStatusByChainId, _BridgeStatusController_handleSolanaTx, _BridgeStatusController_shouldUseSmartTransactions, _BridgeStatusController_handleEvmTransaction, _BridgeStatusController_waitForHashAndReturnFinalTxMeta, _BridgeStatusController_handleSmartTransaction, _BridgeStatusController_addTokens;
|
13
|
+
import { ChainId, formatChainIdToHex, getEthUsdtResetData, isEthUsdt, isNativeAddress, isSolanaChainId } from "@metamask/bridge-controller";
|
14
|
+
import { toHex } from "@metamask/controller-utils";
|
15
|
+
import { EthAccountType } from "@metamask/keyring-api";
|
14
16
|
import { StaticIntervalPollingController } from "@metamask/polling-controller";
|
15
|
-
import {
|
16
|
-
import {
|
17
|
+
import { TransactionType } from "@metamask/transaction-controller";
|
18
|
+
import { createProjectLogger, numberToHex } from "@metamask/utils";
|
19
|
+
import { BigNumber } from "bignumber.js";
|
20
|
+
import { v4 as uuid } from "uuid";
|
21
|
+
import { BRIDGE_PROD_API_BASE_URL, BRIDGE_STATUS_CONTROLLER_NAME, DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE, LINEA_DELAY_MS, REFRESH_INTERVAL_MS } from "./constants.mjs";
|
17
22
|
import { StatusTypes } from "./types.mjs";
|
18
23
|
import { fetchBridgeTxStatus, getStatusRequestWithSrcTxHash } from "./utils/bridge-status.mjs";
|
24
|
+
import { getTxGasEstimates } from "./utils/gas.mjs";
|
25
|
+
import { getStatusRequestParams, getTxMetaFields, handleSolanaTxResponse } from "./utils/transaction.mjs";
|
26
|
+
import { generateActionId } from "./utils/transaction.mjs";
|
19
27
|
const metadata = {
|
20
28
|
// We want to persist the bridge status state so that we can show the proper data for the Activity list
|
21
29
|
// basically match the behavior of TransactionController
|
@@ -25,7 +33,7 @@ const metadata = {
|
|
25
33
|
},
|
26
34
|
};
|
27
35
|
export class BridgeStatusController extends StaticIntervalPollingController() {
|
28
|
-
constructor({ messenger, state, clientId, fetchFn, config, }) {
|
36
|
+
constructor({ messenger, state, clientId, fetchFn, addTransactionFn, addUserOperationFromTransactionFn, estimateGasFeeFn, config, }) {
|
29
37
|
super({
|
30
38
|
name: BRIDGE_STATUS_CONTROLLER_NAME,
|
31
39
|
metadata,
|
@@ -41,6 +49,106 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
41
49
|
_BridgeStatusController_clientId.set(this, void 0);
|
42
50
|
_BridgeStatusController_fetchFn.set(this, void 0);
|
43
51
|
_BridgeStatusController_config.set(this, void 0);
|
52
|
+
_BridgeStatusController_addTransactionFn.set(this, void 0);
|
53
|
+
_BridgeStatusController_addUserOperationFromTransactionFn.set(this, void 0);
|
54
|
+
_BridgeStatusController_estimateGasFeeFn.set(this, void 0);
|
55
|
+
_BridgeStatusController_handleUSDTAllowanceReset.set(this, async (quoteResponse) => {
|
56
|
+
const hexChainId = formatChainIdToHex(quoteResponse.quote.srcChainId);
|
57
|
+
if (quoteResponse.approval &&
|
58
|
+
isEthUsdt(hexChainId, quoteResponse.quote.srcAsset.address)) {
|
59
|
+
const allowance = new BigNumber(await this.messagingSystem.call('BridgeController:getBridgeERC20Allowance', quoteResponse.quote.srcAsset.address, hexChainId));
|
60
|
+
const shouldResetApproval = allowance.lt(quoteResponse.sentAmount.amount) && allowance.gt(0);
|
61
|
+
if (shouldResetApproval) {
|
62
|
+
await __classPrivateFieldGet(this, _BridgeStatusController_handleEvmTransaction, "f").call(this, TransactionType.bridgeApproval, { ...quoteResponse.approval, data: getEthUsdtResetData() }, quoteResponse);
|
63
|
+
}
|
64
|
+
}
|
65
|
+
});
|
66
|
+
_BridgeStatusController_handleLineaDelay.set(this, async (quoteResponse) => {
|
67
|
+
if (ChainId.LINEA === quoteResponse.quote.srcChainId) {
|
68
|
+
const debugLog = createProjectLogger('bridge');
|
69
|
+
debugLog('Delaying submitting bridge tx to make Linea confirmation more likely');
|
70
|
+
const waitPromise = new Promise((resolve) => setTimeout(resolve, LINEA_DELAY_MS));
|
71
|
+
await waitPromise;
|
72
|
+
}
|
73
|
+
});
|
74
|
+
_BridgeStatusController_calculateGasFees.set(this, async (transactionParams, networkClientId, chainId) => {
|
75
|
+
const { gasFeeEstimates } = this.messagingSystem.call('GasFeeController:getState');
|
76
|
+
const { estimates: txGasFeeEstimates } = await __classPrivateFieldGet(this, _BridgeStatusController_estimateGasFeeFn, "f").call(this, {
|
77
|
+
transactionParams,
|
78
|
+
chainId,
|
79
|
+
networkClientId,
|
80
|
+
});
|
81
|
+
const { maxFeePerGas, maxPriorityFeePerGas } = await getTxGasEstimates({
|
82
|
+
networkGasFeeEstimates: gasFeeEstimates,
|
83
|
+
txGasFeeEstimates,
|
84
|
+
});
|
85
|
+
const maxGasLimit = toHex(transactionParams.gas ?? 0);
|
86
|
+
return {
|
87
|
+
maxFeePerGas,
|
88
|
+
maxPriorityFeePerGas,
|
89
|
+
gas: maxGasLimit,
|
90
|
+
};
|
91
|
+
});
|
92
|
+
/**
|
93
|
+
* Submits a cross-chain swap transaction
|
94
|
+
*
|
95
|
+
* @param quoteResponse - The quote response
|
96
|
+
* @param isStxEnabledOnClient - Whether smart transactions are enabled on the client
|
97
|
+
* @returns The transaction meta
|
98
|
+
*/
|
99
|
+
this.submitTx = async (quoteResponse, isStxEnabledOnClient) => {
|
100
|
+
let txMeta;
|
101
|
+
// Submit SOLANA tx
|
102
|
+
if (isSolanaChainId(quoteResponse.quote.srcChainId) &&
|
103
|
+
typeof quoteResponse.trade === 'string') {
|
104
|
+
const { approval, trade, ...partialQuoteResponse } = quoteResponse;
|
105
|
+
txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleSolanaTx, "f").call(this, trade, partialQuoteResponse);
|
106
|
+
}
|
107
|
+
// Submit EVM tx
|
108
|
+
let approvalTime;
|
109
|
+
if (!isSolanaChainId(quoteResponse.quote.srcChainId) &&
|
110
|
+
typeof quoteResponse.trade !== 'string') {
|
111
|
+
let approvalTxId;
|
112
|
+
if (quoteResponse.approval) {
|
113
|
+
await __classPrivateFieldGet(this, _BridgeStatusController_handleUSDTAllowanceReset, "f").call(this, quoteResponse);
|
114
|
+
const approvalTxMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleEvmTransaction, "f").call(this, TransactionType.bridgeApproval, quoteResponse.approval, quoteResponse);
|
115
|
+
if (!approvalTxMeta) {
|
116
|
+
throw new Error('Failed to submit bridge tx: approval txMeta is undefined');
|
117
|
+
}
|
118
|
+
approvalTime = approvalTxMeta.time;
|
119
|
+
approvalTxId = approvalTxMeta.id;
|
120
|
+
await __classPrivateFieldGet(this, _BridgeStatusController_handleLineaDelay, "f").call(this, quoteResponse);
|
121
|
+
}
|
122
|
+
if (__classPrivateFieldGet(this, _BridgeStatusController_shouldUseSmartTransactions, "f").call(this, isStxEnabledOnClient)) {
|
123
|
+
txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleSmartTransaction, "f").call(this, quoteResponse.trade, quoteResponse, approvalTxId);
|
124
|
+
}
|
125
|
+
else {
|
126
|
+
txMeta = await __classPrivateFieldGet(this, _BridgeStatusController_handleEvmTransaction, "f").call(this, TransactionType.bridge, quoteResponse.trade, quoteResponse, approvalTxId);
|
127
|
+
}
|
128
|
+
}
|
129
|
+
__classPrivateFieldGet(this, _BridgeStatusController_addTokens, "f").call(this, quoteResponse.quote.srcAsset);
|
130
|
+
__classPrivateFieldGet(this, _BridgeStatusController_addTokens, "f").call(this, quoteResponse.quote.destAsset);
|
131
|
+
if (!txMeta) {
|
132
|
+
throw new Error('Failed to submit bridge tx: txMeta is undefined');
|
133
|
+
}
|
134
|
+
// Start polling for bridge tx status
|
135
|
+
try {
|
136
|
+
this.startPollingForBridgeTxStatus({
|
137
|
+
bridgeTxMeta: txMeta,
|
138
|
+
statusRequest: {
|
139
|
+
...getStatusRequestParams(quoteResponse),
|
140
|
+
srcTxHash: txMeta.hash,
|
141
|
+
},
|
142
|
+
quoteResponse,
|
143
|
+
slippagePercentage: 0,
|
144
|
+
startTime: approvalTime ?? Date.now(),
|
145
|
+
});
|
146
|
+
}
|
147
|
+
catch {
|
148
|
+
// Ignore errors here, we don't want to crash the app if this fails and tx submission succeeds
|
149
|
+
}
|
150
|
+
return txMeta;
|
151
|
+
};
|
44
152
|
this.resetState = () => {
|
45
153
|
this.update((state) => {
|
46
154
|
state.txHistory = DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.txHistory;
|
@@ -82,6 +190,11 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
82
190
|
});
|
83
191
|
});
|
84
192
|
});
|
193
|
+
/**
|
194
|
+
* Starts polling for the bridge tx status
|
195
|
+
*
|
196
|
+
* @param startPollingForBridgeTxStatusArgs - The args to start polling for the bridge tx status
|
197
|
+
*/
|
85
198
|
this.startPollingForBridgeTxStatus = (startPollingForBridgeTxStatusArgs) => {
|
86
199
|
const { bridgeTxMeta, statusRequest, quoteResponse, startTime, slippagePercentage, initialDestAssetBalance, targetContractAddress, } = startPollingForBridgeTxStatusArgs;
|
87
200
|
const accountAddress = __classPrivateFieldGet(this, _BridgeStatusController_instances, "m", _BridgeStatusController_getMultichainSelectedAccountAddress).call(this);
|
@@ -139,7 +252,7 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
139
252
|
}
|
140
253
|
__classPrivateFieldGet(this, _BridgeStatusController_updateSrcTxHash, "f").call(this, bridgeTxMetaId, srcTxHash);
|
141
254
|
const statusRequest = getStatusRequestWithSrcTxHash(historyItem.quote, srcTxHash);
|
142
|
-
const status = await fetchBridgeTxStatus(statusRequest, __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f"), __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"), __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl
|
255
|
+
const status = await fetchBridgeTxStatus(statusRequest, __classPrivateFieldGet(this, _BridgeStatusController_clientId, "f"), __classPrivateFieldGet(this, _BridgeStatusController_fetchFn, "f"), __classPrivateFieldGet(this, _BridgeStatusController_config, "f").customBridgeApiBaseUrl);
|
143
256
|
const newBridgeHistoryItem = {
|
144
257
|
...historyItem,
|
145
258
|
status,
|
@@ -216,13 +329,193 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
216
329
|
}, state.txHistory);
|
217
330
|
});
|
218
331
|
});
|
332
|
+
/**
|
333
|
+
* Submits a solana swap or bridge transaction using the snap controller
|
334
|
+
*
|
335
|
+
* @param trade - The trade data to confirm
|
336
|
+
* @param quoteResponse - The quote response
|
337
|
+
* @param quoteResponse.quote - The quote
|
338
|
+
* @returns The transaction meta
|
339
|
+
*/
|
340
|
+
_BridgeStatusController_handleSolanaTx.set(this, async (trade, quoteResponse) => {
|
341
|
+
const selectedAccount = __classPrivateFieldGet(this, _BridgeStatusController_instances, "m", _BridgeStatusController_getMultichainSelectedAccount).call(this);
|
342
|
+
if (!selectedAccount) {
|
343
|
+
throw new Error('Failed to submit cross-chain swap transaction: undefined multichain account');
|
344
|
+
}
|
345
|
+
if (!selectedAccount.metadata?.snap?.id ||
|
346
|
+
!selectedAccount.options?.scope) {
|
347
|
+
throw new Error('Failed to submit cross-chain swap transaction: undefined snap id or scope');
|
348
|
+
}
|
349
|
+
/**
|
350
|
+
* Submit the transaction to the snap using the keyring rpc method
|
351
|
+
* This adds an approval tx to the ApprovalsController in the background
|
352
|
+
* The client needs to handle the approval tx by redirecting to the confirmation page with the approvalTxId in the URL
|
353
|
+
*/
|
354
|
+
const keyringReqId = uuid();
|
355
|
+
const snapRequestId = uuid();
|
356
|
+
const keyringResponse = await this.messagingSystem.call('SnapController:handleRequest', {
|
357
|
+
origin: 'metamask',
|
358
|
+
snapId: selectedAccount.metadata.snap.id,
|
359
|
+
handler: 'onKeyringRequest',
|
360
|
+
request: {
|
361
|
+
id: keyringReqId,
|
362
|
+
jsonrpc: '2.0',
|
363
|
+
method: 'keyring_submitRequest',
|
364
|
+
params: {
|
365
|
+
request: {
|
366
|
+
params: {
|
367
|
+
account: { address: selectedAccount.address },
|
368
|
+
transaction: trade,
|
369
|
+
scope: selectedAccount.options.scope,
|
370
|
+
},
|
371
|
+
method: 'signAndSendTransaction',
|
372
|
+
},
|
373
|
+
id: snapRequestId,
|
374
|
+
account: selectedAccount.id,
|
375
|
+
scope: selectedAccount.options.scope,
|
376
|
+
},
|
377
|
+
},
|
378
|
+
});
|
379
|
+
// The extension client actually redirects before it can do anytyhing with this meta
|
380
|
+
const txMeta = handleSolanaTxResponse(keyringResponse, // This is ok bc the snap response can be different types
|
381
|
+
quoteResponse, selectedAccount.metadata.snap.id, selectedAccount.address);
|
382
|
+
// TODO remove this eventually, just returning it now to match extension behavior
|
383
|
+
// OR if the snap can propagate the snapRequestId or keyringReqId to the ApprovalsControlle, this can return the approvalTxId instead and clients won't need to subscribe to the ApprovalsController state to redirect
|
384
|
+
return {
|
385
|
+
...txMeta,
|
386
|
+
keyringReqId,
|
387
|
+
snapRequestId,
|
388
|
+
};
|
389
|
+
});
|
390
|
+
_BridgeStatusController_shouldUseSmartTransactions.set(this, (isStxEnabledOnClient) => {
|
391
|
+
const isUserOptedInToStx = this.messagingSystem.call('PreferencesController:getState').smartTransactionsOptInStatus;
|
392
|
+
// User has no opt in status, use default value from client
|
393
|
+
return ((isUserOptedInToStx ?? __classPrivateFieldGet(this, _BridgeStatusController_config, "f").smartTransactionsEnabledByDefault) &&
|
394
|
+
isStxEnabledOnClient);
|
395
|
+
});
|
396
|
+
/**
|
397
|
+
* Submits an EVM transaction to the TransactionController
|
398
|
+
*
|
399
|
+
* @param transactionType - The type of transaction to submit
|
400
|
+
* @param trade - The trade data to confirm
|
401
|
+
* @param quoteResponse - The quote response
|
402
|
+
* @param quoteResponse.quote - The quote
|
403
|
+
* @param approvalTxId - The tx id of the approval tx
|
404
|
+
* @param shouldWaitForHash - Whether to wait for the hash of the transaction
|
405
|
+
* @returns The transaction meta
|
406
|
+
*/
|
407
|
+
_BridgeStatusController_handleEvmTransaction.set(this, async (transactionType, trade, quoteResponse, approvalTxId, shouldWaitForHash = true) => {
|
408
|
+
const actionId = generateActionId().toString();
|
409
|
+
const selectedAccount = this.messagingSystem.call('AccountsController:getAccountByAddress', trade.from);
|
410
|
+
if (!selectedAccount) {
|
411
|
+
throw new Error('Failed to submit cross-chain swap transaction: unknown account in trade data');
|
412
|
+
}
|
413
|
+
const hexChainId = formatChainIdToHex(trade.chainId);
|
414
|
+
const networkClientId = this.messagingSystem.call('NetworkController:findNetworkClientIdByChainId', hexChainId);
|
415
|
+
const requestOptions = {
|
416
|
+
actionId,
|
417
|
+
networkClientId,
|
418
|
+
requireApproval: false,
|
419
|
+
type: transactionType,
|
420
|
+
origin: 'metamask',
|
421
|
+
};
|
422
|
+
const transactionParams = {
|
423
|
+
...trade,
|
424
|
+
chainId: hexChainId,
|
425
|
+
gasLimit: trade.gasLimit?.toString(),
|
426
|
+
gas: trade.gasLimit?.toString(),
|
427
|
+
};
|
428
|
+
const transactionParamsWithMaxGas = {
|
429
|
+
...transactionParams,
|
430
|
+
...(await __classPrivateFieldGet(this, _BridgeStatusController_calculateGasFees, "f").call(this, transactionParams, networkClientId, hexChainId)),
|
431
|
+
};
|
432
|
+
let result;
|
433
|
+
let transactionMeta;
|
434
|
+
const isSmartContractAccount = selectedAccount.type === EthAccountType.Erc4337;
|
435
|
+
if (isSmartContractAccount) {
|
436
|
+
const userOperationResult = await __classPrivateFieldGet(this, _BridgeStatusController_addUserOperationFromTransactionFn, "f").call(this, transactionParamsWithMaxGas, requestOptions);
|
437
|
+
// TODO return hash and txMeta from UserOperationController.addUserOperationFromTransaction
|
438
|
+
transactionMeta = {
|
439
|
+
id: userOperationResult.id,
|
440
|
+
};
|
441
|
+
// result = userOperationResult.hash();
|
442
|
+
}
|
443
|
+
else {
|
444
|
+
const addTransactionResult = await __classPrivateFieldGet(this, _BridgeStatusController_addTransactionFn, "f").call(this, transactionParamsWithMaxGas, requestOptions);
|
445
|
+
result = addTransactionResult.result;
|
446
|
+
transactionMeta = addTransactionResult.transactionMeta;
|
447
|
+
}
|
448
|
+
// Note that updateTransaction doesn't actually error if you add fields that don't conform the to the txMeta type
|
449
|
+
// they will be there at runtime, but you just don't get any type safety checks on them
|
450
|
+
const completeTxMeta = {
|
451
|
+
...transactionMeta,
|
452
|
+
...getTxMetaFields(quoteResponse, approvalTxId),
|
453
|
+
};
|
454
|
+
// TODO why is this needed? Can we skip update and directly pass txMetaFields to TransactionController.addTransctin call
|
455
|
+
// const fieldsToAddToTxMeta = getTxMetaFields(quoteResponse, approvalTxId);
|
456
|
+
// dispatch(updateTransaction(completeTxMeta);
|
457
|
+
if (shouldWaitForHash) {
|
458
|
+
return await __classPrivateFieldGet(this, _BridgeStatusController_waitForHashAndReturnFinalTxMeta, "f").call(this, result);
|
459
|
+
}
|
460
|
+
return completeTxMeta;
|
461
|
+
});
|
462
|
+
_BridgeStatusController_waitForHashAndReturnFinalTxMeta.set(this, async (hashPromise) => {
|
463
|
+
const transactionHash = await hashPromise;
|
464
|
+
const finalTransactionMeta = this.messagingSystem
|
465
|
+
.call('TransactionController:getState')
|
466
|
+
.transactions.find((tx) => tx.hash === transactionHash);
|
467
|
+
return finalTransactionMeta;
|
468
|
+
});
|
469
|
+
/**
|
470
|
+
* Submits a smart transaction
|
471
|
+
*
|
472
|
+
* @param trade - The trade data to confirm
|
473
|
+
* @param quoteResponse - The quote response
|
474
|
+
* @param quoteResponse.quote - The quote
|
475
|
+
* @param approvalTxId - The tx id of the approval tx
|
476
|
+
* @returns The transaction meta
|
477
|
+
*/
|
478
|
+
_BridgeStatusController_handleSmartTransaction.set(this, async (trade, quoteResponse, approvalTxId) => {
|
479
|
+
return await __classPrivateFieldGet(this, _BridgeStatusController_handleEvmTransaction, "f").call(this, TransactionType.bridge, trade, quoteResponse, approvalTxId, false);
|
480
|
+
});
|
481
|
+
// Only add tokens if the source or dest chain is an EVM chain bc non-evm tokens
|
482
|
+
// are detected by the multichain asset controllers
|
483
|
+
_BridgeStatusController_addTokens.set(this, (asset) => {
|
484
|
+
// Return early if the asset chain is native or if asset is in the solana chain
|
485
|
+
if (isNativeAddress(asset.address) || isSolanaChainId(asset.chainId)) {
|
486
|
+
return;
|
487
|
+
}
|
488
|
+
this.messagingSystem
|
489
|
+
.call('TokensController:addDetectedTokens', [
|
490
|
+
{
|
491
|
+
address: asset.address,
|
492
|
+
decimals: asset.decimals,
|
493
|
+
image: asset.iconUrl,
|
494
|
+
name: asset.name,
|
495
|
+
symbol: asset.symbol,
|
496
|
+
},
|
497
|
+
], {
|
498
|
+
chainId: formatChainIdToHex(asset.chainId),
|
499
|
+
selectedAddress: __classPrivateFieldGet(this, _BridgeStatusController_instances, "m", _BridgeStatusController_getMultichainSelectedAccountAddress).call(this),
|
500
|
+
})
|
501
|
+
.catch(() => {
|
502
|
+
// Ignore errors
|
503
|
+
});
|
504
|
+
});
|
219
505
|
__classPrivateFieldSet(this, _BridgeStatusController_clientId, clientId, "f");
|
220
506
|
__classPrivateFieldSet(this, _BridgeStatusController_fetchFn, fetchFn, "f");
|
221
|
-
__classPrivateFieldSet(this,
|
507
|
+
__classPrivateFieldSet(this, _BridgeStatusController_addTransactionFn, addTransactionFn, "f");
|
508
|
+
__classPrivateFieldSet(this, _BridgeStatusController_addUserOperationFromTransactionFn, addUserOperationFromTransactionFn, "f");
|
509
|
+
__classPrivateFieldSet(this, _BridgeStatusController_estimateGasFeeFn, estimateGasFeeFn, "f");
|
510
|
+
__classPrivateFieldSet(this, _BridgeStatusController_config, {
|
511
|
+
customBridgeApiBaseUrl: config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,
|
512
|
+
smartTransactionsEnabledByDefault: config.smartTransactionsEnabledByDefault,
|
513
|
+
}, "f");
|
222
514
|
// Register action handlers
|
223
515
|
this.messagingSystem.registerActionHandler(`${BRIDGE_STATUS_CONTROLLER_NAME}:startPollingForBridgeTxStatus`, this.startPollingForBridgeTxStatus.bind(this));
|
224
516
|
this.messagingSystem.registerActionHandler(`${BRIDGE_STATUS_CONTROLLER_NAME}:wipeBridgeStatus`, this.wipeBridgeStatus.bind(this));
|
225
517
|
this.messagingSystem.registerActionHandler(`${BRIDGE_STATUS_CONTROLLER_NAME}:resetState`, this.resetState.bind(this));
|
518
|
+
this.messagingSystem.registerActionHandler(`${BRIDGE_STATUS_CONTROLLER_NAME}:submitTx`, this.submitTx.bind(this));
|
226
519
|
// Set interval
|
227
520
|
this.setIntervalLength(REFRESH_INTERVAL_MS);
|
228
521
|
// If you close the extension, but keep the browser open, the polling continues
|
@@ -231,7 +524,9 @@ export class BridgeStatusController extends StaticIntervalPollingController() {
|
|
231
524
|
__classPrivateFieldGet(this, _BridgeStatusController_restartPollingForIncompleteHistoryItems, "f").call(this);
|
232
525
|
}
|
233
526
|
}
|
234
|
-
_BridgeStatusController_pollingTokensByTxMetaId = new WeakMap(), _BridgeStatusController_clientId = new WeakMap(), _BridgeStatusController_fetchFn = new WeakMap(), _BridgeStatusController_config = new WeakMap(), _BridgeStatusController_restartPollingForIncompleteHistoryItems = new WeakMap(), _BridgeStatusController_fetchBridgeTxStatus = new WeakMap(), _BridgeStatusController_getSrcTxHash = new WeakMap(), _BridgeStatusController_updateSrcTxHash = new WeakMap(), _BridgeStatusController_wipeBridgeStatusByChainId = new WeakMap(), _BridgeStatusController_instances = new WeakSet(),
|
235
|
-
return
|
527
|
+
_BridgeStatusController_pollingTokensByTxMetaId = new WeakMap(), _BridgeStatusController_clientId = new WeakMap(), _BridgeStatusController_fetchFn = new WeakMap(), _BridgeStatusController_config = new WeakMap(), _BridgeStatusController_addTransactionFn = new WeakMap(), _BridgeStatusController_addUserOperationFromTransactionFn = new WeakMap(), _BridgeStatusController_estimateGasFeeFn = new WeakMap(), _BridgeStatusController_handleUSDTAllowanceReset = new WeakMap(), _BridgeStatusController_handleLineaDelay = new WeakMap(), _BridgeStatusController_calculateGasFees = new WeakMap(), _BridgeStatusController_restartPollingForIncompleteHistoryItems = new WeakMap(), _BridgeStatusController_fetchBridgeTxStatus = new WeakMap(), _BridgeStatusController_getSrcTxHash = new WeakMap(), _BridgeStatusController_updateSrcTxHash = new WeakMap(), _BridgeStatusController_wipeBridgeStatusByChainId = new WeakMap(), _BridgeStatusController_handleSolanaTx = new WeakMap(), _BridgeStatusController_shouldUseSmartTransactions = new WeakMap(), _BridgeStatusController_handleEvmTransaction = new WeakMap(), _BridgeStatusController_waitForHashAndReturnFinalTxMeta = new WeakMap(), _BridgeStatusController_handleSmartTransaction = new WeakMap(), _BridgeStatusController_addTokens = new WeakMap(), _BridgeStatusController_instances = new WeakSet(), _BridgeStatusController_getMultichainSelectedAccount = function _BridgeStatusController_getMultichainSelectedAccount() {
|
528
|
+
return this.messagingSystem.call('AccountsController:getSelectedMultichainAccount');
|
529
|
+
}, _BridgeStatusController_getMultichainSelectedAccountAddress = function _BridgeStatusController_getMultichainSelectedAccountAddress() {
|
530
|
+
return __classPrivateFieldGet(this, _BridgeStatusController_instances, "m", _BridgeStatusController_getMultichainSelectedAccount).call(this)?.address ?? '';
|
236
531
|
};
|
237
532
|
//# sourceMappingURL=bridge-status-controller.mjs.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"bridge-status-controller.mjs","sourceRoot":"","sources":["../src/bridge-status-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StateMetadata } from '@metamask/base-controller';\nimport type { BridgeClientId } from '@metamask/bridge-controller';\nimport { BRIDGE_PROD_API_BASE_URL } from '@metamask/bridge-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { numberToHex, type Hex } from '@metamask/utils';\n\nimport {\n BRIDGE_STATUS_CONTROLLER_NAME,\n DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE,\n REFRESH_INTERVAL_MS,\n} from './constants';\nimport { StatusTypes, type BridgeStatusControllerMessenger } from './types';\nimport type {\n BridgeStatusControllerState,\n StartPollingForBridgeTxStatusArgsSerialized,\n FetchFunction,\n} from './types';\nimport {\n fetchBridgeTxStatus,\n getStatusRequestWithSrcTxHash,\n} from './utils/bridge-status';\n\nconst metadata: StateMetadata<BridgeStatusControllerState> = {\n // We want to persist the bridge status state so that we can show the proper data for the Activity list\n // basically match the behavior of TransactionController\n txHistory: {\n persist: true,\n anonymous: false,\n },\n};\n\n/** The input to start polling for the {@link BridgeStatusController} */\ntype BridgeStatusPollingInput = FetchBridgeTxStatusArgs;\n\ntype SrcTxMetaId = string;\nexport type FetchBridgeTxStatusArgs = {\n bridgeTxMetaId: string;\n};\nexport class BridgeStatusController extends StaticIntervalPollingController<BridgeStatusPollingInput>()<\n typeof BRIDGE_STATUS_CONTROLLER_NAME,\n BridgeStatusControllerState,\n BridgeStatusControllerMessenger\n> {\n #pollingTokensByTxMetaId: Record<SrcTxMetaId, string> = {};\n\n readonly #clientId: BridgeClientId;\n\n readonly #fetchFn: FetchFunction;\n\n readonly #config: {\n customBridgeApiBaseUrl?: string;\n };\n\n constructor({\n messenger,\n state,\n clientId,\n fetchFn,\n config,\n }: {\n messenger: BridgeStatusControllerMessenger;\n state?: Partial<BridgeStatusControllerState>;\n clientId: BridgeClientId;\n fetchFn: FetchFunction;\n config?: {\n customBridgeApiBaseUrl?: string;\n };\n }) {\n super({\n name: BRIDGE_STATUS_CONTROLLER_NAME,\n metadata,\n messenger,\n // Restore the persisted state\n state: {\n ...DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE,\n ...state,\n },\n });\n\n this.#clientId = clientId;\n this.#fetchFn = fetchFn;\n this.#config = config ?? {};\n\n // Register action handlers\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_STATUS_CONTROLLER_NAME}:startPollingForBridgeTxStatus`,\n this.startPollingForBridgeTxStatus.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_STATUS_CONTROLLER_NAME}:wipeBridgeStatus`,\n this.wipeBridgeStatus.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_STATUS_CONTROLLER_NAME}:resetState`,\n this.resetState.bind(this),\n );\n\n // Set interval\n this.setIntervalLength(REFRESH_INTERVAL_MS);\n\n // If you close the extension, but keep the browser open, the polling continues\n // If you close the browser, the polling stops\n // Check for historyItems that do not have a status of complete and restart polling\n this.#restartPollingForIncompleteHistoryItems();\n }\n\n resetState = () => {\n this.update((state) => {\n state.txHistory = DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.txHistory;\n });\n };\n\n wipeBridgeStatus = ({\n address,\n ignoreNetwork,\n }: {\n address: string;\n ignoreNetwork: boolean;\n }) => {\n // Wipe all networks for this address\n if (ignoreNetwork) {\n this.update((state) => {\n state.txHistory = DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.txHistory;\n });\n } else {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const selectedNetworkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n const selectedChainId = selectedNetworkClient.configuration.chainId;\n\n this.#wipeBridgeStatusByChainId(address, selectedChainId);\n }\n };\n\n readonly #restartPollingForIncompleteHistoryItems = () => {\n // Check for historyItems that do not have a status of complete and restart polling\n const { txHistory } = this.state;\n const historyItems = Object.values(txHistory);\n const incompleteHistoryItems = historyItems\n .filter(\n (historyItem) =>\n historyItem.status.status === StatusTypes.PENDING ||\n historyItem.status.status === StatusTypes.UNKNOWN,\n )\n .filter((historyItem) => {\n // Check if we are already polling this tx, if so, skip restarting polling for that\n const srcTxMetaId = historyItem.txMetaId;\n const pollingToken = this.#pollingTokensByTxMetaId[srcTxMetaId];\n return !pollingToken;\n });\n\n incompleteHistoryItems.forEach((historyItem) => {\n const bridgeTxMetaId = historyItem.txMetaId;\n\n // We manually call startPolling() here rather than go through startPollingForBridgeTxStatus()\n // because we don't want to overwrite the existing historyItem in state\n this.#pollingTokensByTxMetaId[bridgeTxMetaId] = this.startPolling({\n bridgeTxMetaId,\n });\n });\n };\n\n startPollingForBridgeTxStatus = (\n startPollingForBridgeTxStatusArgs: StartPollingForBridgeTxStatusArgsSerialized,\n ) => {\n const {\n bridgeTxMeta,\n statusRequest,\n quoteResponse,\n startTime,\n slippagePercentage,\n initialDestAssetBalance,\n targetContractAddress,\n } = startPollingForBridgeTxStatusArgs;\n const accountAddress = this.#getMultichainSelectedAccountAddress();\n // Write all non-status fields to state so we can reference the quote in Activity list without the Bridge API\n // We know it's in progress but not the exact status yet\n const txHistoryItem = {\n txMetaId: bridgeTxMeta.id,\n quote: quoteResponse.quote,\n startTime,\n estimatedProcessingTimeInSeconds:\n quoteResponse.estimatedProcessingTimeInSeconds,\n slippagePercentage,\n pricingData: {\n amountSent: quoteResponse.sentAmount.amount,\n amountSentInUsd: quoteResponse.sentAmount.usd ?? undefined,\n quotedGasInUsd: quoteResponse.gasFee.usd ?? undefined,\n quotedReturnInUsd: quoteResponse.toTokenAmount.usd ?? undefined,\n },\n initialDestAssetBalance,\n targetContractAddress,\n account: accountAddress,\n status: {\n // We always have a PENDING status when we start polling for a tx, don't need the Bridge API for that\n // Also we know the bare minimum fields for status at this point in time\n status: StatusTypes.PENDING,\n srcChain: {\n chainId: statusRequest.srcChainId,\n txHash: statusRequest.srcTxHash,\n },\n },\n hasApprovalTx: Boolean(quoteResponse.approval),\n };\n this.update((state) => {\n // Use the txMeta.id as the key so we can reference the txMeta in TransactionController\n state.txHistory[bridgeTxMeta.id] = txHistoryItem;\n });\n\n this.#pollingTokensByTxMetaId[bridgeTxMeta.id] = this.startPolling({\n bridgeTxMetaId: bridgeTxMeta.id,\n });\n };\n\n // This will be called after you call this.startPolling()\n // The args passed in are the args you passed in to startPolling()\n _executePoll = async (pollingInput: BridgeStatusPollingInput) => {\n await this.#fetchBridgeTxStatus(pollingInput);\n };\n\n #getMultichainSelectedAccountAddress() {\n return (\n this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n )?.address ?? ''\n );\n }\n\n readonly #fetchBridgeTxStatus = async ({\n bridgeTxMetaId,\n }: FetchBridgeTxStatusArgs) => {\n const { txHistory } = this.state;\n\n try {\n // We try here because we receive 500 errors from Bridge API if we try to fetch immediately after submitting the source tx\n // Oddly mostly happens on Optimism, never on Arbitrum. By the 2nd fetch, the Bridge API responds properly.\n // Also srcTxHash may not be available immediately for STX, so we don't want to fetch in those cases\n const historyItem = txHistory[bridgeTxMetaId];\n const srcTxHash = this.#getSrcTxHash(bridgeTxMetaId);\n if (!srcTxHash) {\n return;\n }\n\n this.#updateSrcTxHash(bridgeTxMetaId, srcTxHash);\n\n const statusRequest = getStatusRequestWithSrcTxHash(\n historyItem.quote,\n srcTxHash,\n );\n const status = await fetchBridgeTxStatus(\n statusRequest,\n this.#clientId,\n this.#fetchFn,\n this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n const newBridgeHistoryItem = {\n ...historyItem,\n status,\n completionTime:\n status.status === StatusTypes.COMPLETE ||\n status.status === StatusTypes.FAILED\n ? Date.now()\n : undefined, // TODO make this more accurate by looking up dest txHash block time\n };\n\n // No need to purge these on network change or account change, TransactionController does not purge either.\n // TODO In theory we can skip checking status if it's not the current account/network\n // we need to keep track of the account that this is associated with as well so that we don't show it in Activity list for other accounts\n // First stab at this will not stop polling when you are on a different account\n this.update((state) => {\n state.txHistory[bridgeTxMetaId] = newBridgeHistoryItem;\n });\n\n const pollingToken = this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n\n if (\n (status.status === StatusTypes.COMPLETE ||\n status.status === StatusTypes.FAILED) &&\n pollingToken\n ) {\n this.stopPollingByPollingToken(pollingToken);\n\n if (status.status === StatusTypes.COMPLETE) {\n this.messagingSystem.publish(\n `${BRIDGE_STATUS_CONTROLLER_NAME}:bridgeTransactionComplete`,\n { bridgeHistoryItem: newBridgeHistoryItem },\n );\n }\n if (status.status === StatusTypes.FAILED) {\n this.messagingSystem.publish(\n `${BRIDGE_STATUS_CONTROLLER_NAME}:bridgeTransactionFailed`,\n { bridgeHistoryItem: newBridgeHistoryItem },\n );\n }\n }\n } catch (e) {\n console.log('Failed to fetch bridge tx status', e);\n }\n };\n\n readonly #getSrcTxHash = (bridgeTxMetaId: string): string | undefined => {\n const { txHistory } = this.state;\n // Prefer the srcTxHash from bridgeStatusState so we don't have to l ook up in TransactionController\n // But it is possible to have bridgeHistoryItem in state without the srcTxHash yet when it is an STX\n const srcTxHash = txHistory[bridgeTxMetaId].status.srcChain.txHash;\n\n if (srcTxHash) {\n return srcTxHash;\n }\n\n // Look up in TransactionController if txMeta has been updated with the srcTxHash\n const txControllerState = this.messagingSystem.call(\n 'TransactionController:getState',\n );\n const txMeta = txControllerState.transactions.find(\n (tx) => tx.id === bridgeTxMetaId,\n );\n return txMeta?.hash;\n };\n\n readonly #updateSrcTxHash = (bridgeTxMetaId: string, srcTxHash: string) => {\n const { txHistory } = this.state;\n if (txHistory[bridgeTxMetaId].status.srcChain.txHash) {\n return;\n }\n\n this.update((state) => {\n state.txHistory[bridgeTxMetaId].status.srcChain.txHash = srcTxHash;\n });\n };\n\n // Wipes the bridge status for the given address and chainId\n // Will match only source chainId to the selectedChainId\n readonly #wipeBridgeStatusByChainId = (\n address: string,\n selectedChainId: Hex,\n ) => {\n const sourceTxMetaIdsToDelete = Object.keys(this.state.txHistory).filter(\n (txMetaId) => {\n const bridgeHistoryItem = this.state.txHistory[txMetaId];\n\n const hexSourceChainId = numberToHex(\n bridgeHistoryItem.quote.srcChainId,\n );\n\n return (\n bridgeHistoryItem.account === address &&\n hexSourceChainId === selectedChainId\n );\n },\n );\n\n sourceTxMetaIdsToDelete.forEach((sourceTxMetaId) => {\n const pollingToken = this.#pollingTokensByTxMetaId[sourceTxMetaId];\n\n if (pollingToken) {\n this.stopPollingByPollingToken(\n this.#pollingTokensByTxMetaId[sourceTxMetaId],\n );\n }\n });\n\n this.update((state) => {\n state.txHistory = sourceTxMetaIdsToDelete.reduce(\n (acc, sourceTxMetaId) => {\n delete acc[sourceTxMetaId];\n return acc;\n },\n state.txHistory,\n );\n });\n };\n}\n"]}
|
1
|
+
{"version":3,"file":"bridge-status-controller.mjs","sourceRoot":"","sources":["../src/bridge-status-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StateMetadata } from '@metamask/base-controller';\nimport {\n ChainId,\n formatChainIdToHex,\n getEthUsdtResetData,\n isEthUsdt,\n isNativeAddress,\n isSolanaChainId,\n type QuoteResponse,\n} from '@metamask/bridge-controller';\nimport type {\n BridgeAsset,\n QuoteMetadata,\n TxData,\n} from '@metamask/bridge-controller';\nimport { toHex } from '@metamask/controller-utils';\nimport { EthAccountType } from '@metamask/keyring-api';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type {\n TransactionController,\n TransactionParams,\n} from '@metamask/transaction-controller';\nimport {\n TransactionType,\n type TransactionMeta,\n} from '@metamask/transaction-controller';\nimport type { UserOperationController } from '@metamask/user-operation-controller';\nimport { createProjectLogger, numberToHex, type Hex } from '@metamask/utils';\nimport { BigNumber } from 'bignumber.js';\nimport { v4 as uuid } from 'uuid';\n\nimport {\n BRIDGE_PROD_API_BASE_URL,\n BRIDGE_STATUS_CONTROLLER_NAME,\n DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE,\n LINEA_DELAY_MS,\n REFRESH_INTERVAL_MS,\n} from './constants';\nimport { StatusTypes, type BridgeStatusControllerMessenger } from './types';\nimport type {\n BridgeStatusControllerState,\n StartPollingForBridgeTxStatusArgsSerialized,\n FetchFunction,\n BridgeClientId,\n} from './types';\nimport {\n fetchBridgeTxStatus,\n getStatusRequestWithSrcTxHash,\n} from './utils/bridge-status';\nimport { getTxGasEstimates } from './utils/gas';\nimport {\n getStatusRequestParams,\n getTxMetaFields,\n handleSolanaTxResponse,\n} from './utils/transaction';\nimport { generateActionId } from './utils/transaction';\n\nconst metadata: StateMetadata<BridgeStatusControllerState> = {\n // We want to persist the bridge status state so that we can show the proper data for the Activity list\n // basically match the behavior of TransactionController\n txHistory: {\n persist: true,\n anonymous: false,\n },\n};\n\n/** The input to start polling for the {@link BridgeStatusController} */\ntype BridgeStatusPollingInput = FetchBridgeTxStatusArgs;\n\ntype SrcTxMetaId = string;\nexport type FetchBridgeTxStatusArgs = {\n bridgeTxMetaId: string;\n};\nexport class BridgeStatusController extends StaticIntervalPollingController<BridgeStatusPollingInput>()<\n typeof BRIDGE_STATUS_CONTROLLER_NAME,\n BridgeStatusControllerState,\n BridgeStatusControllerMessenger\n> {\n #pollingTokensByTxMetaId: Record<SrcTxMetaId, string> = {};\n\n readonly #clientId: BridgeClientId;\n\n readonly #fetchFn: FetchFunction;\n\n readonly #config: {\n customBridgeApiBaseUrl: string;\n smartTransactionsEnabledByDefault: boolean;\n };\n\n readonly #addTransactionFn: typeof TransactionController.prototype.addTransaction;\n\n readonly #addUserOperationFromTransactionFn: typeof UserOperationController.prototype.addUserOperationFromTransaction;\n\n readonly #estimateGasFeeFn: typeof TransactionController.prototype.estimateGasFee;\n\n constructor({\n messenger,\n state,\n clientId,\n fetchFn,\n addTransactionFn,\n addUserOperationFromTransactionFn,\n estimateGasFeeFn,\n config,\n }: {\n messenger: BridgeStatusControllerMessenger;\n state?: Partial<BridgeStatusControllerState>;\n clientId: BridgeClientId;\n fetchFn: FetchFunction;\n addTransactionFn: typeof TransactionController.prototype.addTransaction;\n estimateGasFeeFn: typeof TransactionController.prototype.estimateGasFee;\n addUserOperationFromTransactionFn: typeof UserOperationController.prototype.addUserOperationFromTransaction;\n config: {\n customBridgeApiBaseUrl?: string;\n smartTransactionsEnabledByDefault: boolean;\n };\n }) {\n super({\n name: BRIDGE_STATUS_CONTROLLER_NAME,\n metadata,\n messenger,\n // Restore the persisted state\n state: {\n ...DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE,\n ...state,\n },\n });\n\n this.#clientId = clientId;\n this.#fetchFn = fetchFn;\n this.#addTransactionFn = addTransactionFn;\n this.#addUserOperationFromTransactionFn = addUserOperationFromTransactionFn;\n this.#estimateGasFeeFn = estimateGasFeeFn;\n this.#config = {\n customBridgeApiBaseUrl:\n config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n smartTransactionsEnabledByDefault:\n config.smartTransactionsEnabledByDefault,\n };\n\n // Register action handlers\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_STATUS_CONTROLLER_NAME}:startPollingForBridgeTxStatus`,\n this.startPollingForBridgeTxStatus.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_STATUS_CONTROLLER_NAME}:wipeBridgeStatus`,\n this.wipeBridgeStatus.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_STATUS_CONTROLLER_NAME}:resetState`,\n this.resetState.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_STATUS_CONTROLLER_NAME}:submitTx`,\n this.submitTx.bind(this),\n );\n\n // Set interval\n this.setIntervalLength(REFRESH_INTERVAL_MS);\n\n // If you close the extension, but keep the browser open, the polling continues\n // If you close the browser, the polling stops\n // Check for historyItems that do not have a status of complete and restart polling\n this.#restartPollingForIncompleteHistoryItems();\n }\n\n readonly #handleUSDTAllowanceReset = async (\n quoteResponse: QuoteResponse<TxData | string> & QuoteMetadata,\n ) => {\n const hexChainId = formatChainIdToHex(quoteResponse.quote.srcChainId);\n if (\n quoteResponse.approval &&\n isEthUsdt(hexChainId, quoteResponse.quote.srcAsset.address)\n ) {\n const allowance = new BigNumber(\n await this.messagingSystem.call(\n 'BridgeController:getBridgeERC20Allowance',\n quoteResponse.quote.srcAsset.address,\n hexChainId,\n ),\n );\n const shouldResetApproval =\n allowance.lt(quoteResponse.sentAmount.amount) && allowance.gt(0);\n if (shouldResetApproval) {\n await this.#handleEvmTransaction(\n TransactionType.bridgeApproval,\n { ...quoteResponse.approval, data: getEthUsdtResetData() },\n quoteResponse,\n );\n }\n }\n };\n\n readonly #handleLineaDelay = async (\n quoteResponse: QuoteResponse<TxData | string>,\n ) => {\n if (ChainId.LINEA === quoteResponse.quote.srcChainId) {\n const debugLog = createProjectLogger('bridge');\n debugLog(\n 'Delaying submitting bridge tx to make Linea confirmation more likely',\n );\n const waitPromise = new Promise((resolve) =>\n setTimeout(resolve, LINEA_DELAY_MS),\n );\n await waitPromise;\n }\n };\n\n readonly #calculateGasFees = async (\n transactionParams: TransactionParams,\n networkClientId: string,\n chainId: Hex,\n ) => {\n const { gasFeeEstimates } = this.messagingSystem.call(\n 'GasFeeController:getState',\n );\n const { estimates: txGasFeeEstimates } = await this.#estimateGasFeeFn({\n transactionParams,\n chainId,\n networkClientId,\n });\n const { maxFeePerGas, maxPriorityFeePerGas } = await getTxGasEstimates({\n networkGasFeeEstimates: gasFeeEstimates,\n txGasFeeEstimates,\n });\n const maxGasLimit = toHex(transactionParams.gas ?? 0);\n\n return {\n maxFeePerGas,\n maxPriorityFeePerGas,\n gas: maxGasLimit,\n };\n };\n\n /**\n * Submits a cross-chain swap transaction\n *\n * @param quoteResponse - The quote response\n * @param isStxEnabledOnClient - Whether smart transactions are enabled on the client\n * @returns The transaction meta\n */\n submitTx = async (\n quoteResponse: QuoteResponse<TxData | string> & QuoteMetadata,\n isStxEnabledOnClient: boolean,\n ) => {\n let txMeta: TransactionMeta | undefined;\n // Submit SOLANA tx\n if (\n isSolanaChainId(quoteResponse.quote.srcChainId) &&\n typeof quoteResponse.trade === 'string'\n ) {\n const { approval, trade, ...partialQuoteResponse } = quoteResponse;\n txMeta = await this.#handleSolanaTx(trade, partialQuoteResponse);\n }\n // Submit EVM tx\n let approvalTime: number | undefined;\n if (\n !isSolanaChainId(quoteResponse.quote.srcChainId) &&\n typeof quoteResponse.trade !== 'string'\n ) {\n let approvalTxId: string | undefined;\n if (quoteResponse.approval) {\n await this.#handleUSDTAllowanceReset(quoteResponse);\n const approvalTxMeta = await this.#handleEvmTransaction(\n TransactionType.bridgeApproval,\n quoteResponse.approval,\n quoteResponse,\n );\n if (!approvalTxMeta) {\n throw new Error(\n 'Failed to submit bridge tx: approval txMeta is undefined',\n );\n }\n approvalTime = approvalTxMeta.time;\n approvalTxId = approvalTxMeta.id;\n\n await this.#handleLineaDelay(quoteResponse);\n }\n if (this.#shouldUseSmartTransactions(isStxEnabledOnClient)) {\n txMeta = await this.#handleSmartTransaction(\n quoteResponse.trade,\n quoteResponse,\n approvalTxId,\n );\n } else {\n txMeta = await this.#handleEvmTransaction(\n TransactionType.bridge,\n quoteResponse.trade,\n quoteResponse,\n approvalTxId,\n );\n }\n }\n\n this.#addTokens(quoteResponse.quote.srcAsset);\n this.#addTokens(quoteResponse.quote.destAsset);\n\n if (!txMeta) {\n throw new Error('Failed to submit bridge tx: txMeta is undefined');\n }\n\n // Start polling for bridge tx status\n try {\n this.startPollingForBridgeTxStatus({\n bridgeTxMeta: txMeta, // Only the id field is used by the BridgeStatusController\n statusRequest: {\n ...getStatusRequestParams(quoteResponse),\n srcTxHash: txMeta.hash,\n },\n quoteResponse,\n slippagePercentage: 0, // TODO include slippage provided by quote if using dynamic slippage, or slippage from quote request\n startTime: approvalTime ?? Date.now(),\n });\n } catch {\n // Ignore errors here, we don't want to crash the app if this fails and tx submission succeeds\n }\n return txMeta;\n };\n\n resetState = () => {\n this.update((state) => {\n state.txHistory = DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.txHistory;\n });\n };\n\n wipeBridgeStatus = ({\n address,\n ignoreNetwork,\n }: {\n address: string;\n ignoreNetwork: boolean;\n }) => {\n // Wipe all networks for this address\n if (ignoreNetwork) {\n this.update((state) => {\n state.txHistory = DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE.txHistory;\n });\n } else {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n const selectedNetworkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n const selectedChainId = selectedNetworkClient.configuration.chainId;\n\n this.#wipeBridgeStatusByChainId(address, selectedChainId);\n }\n };\n\n readonly #restartPollingForIncompleteHistoryItems = () => {\n // Check for historyItems that do not have a status of complete and restart polling\n const { txHistory } = this.state;\n const historyItems = Object.values(txHistory);\n const incompleteHistoryItems = historyItems\n .filter(\n (historyItem) =>\n historyItem.status.status === StatusTypes.PENDING ||\n historyItem.status.status === StatusTypes.UNKNOWN,\n )\n .filter((historyItem) => {\n // Check if we are already polling this tx, if so, skip restarting polling for that\n const srcTxMetaId = historyItem.txMetaId;\n const pollingToken = this.#pollingTokensByTxMetaId[srcTxMetaId];\n return !pollingToken;\n });\n\n incompleteHistoryItems.forEach((historyItem) => {\n const bridgeTxMetaId = historyItem.txMetaId;\n\n // We manually call startPolling() here rather than go through startPollingForBridgeTxStatus()\n // because we don't want to overwrite the existing historyItem in state\n this.#pollingTokensByTxMetaId[bridgeTxMetaId] = this.startPolling({\n bridgeTxMetaId,\n });\n });\n };\n\n /**\n * Starts polling for the bridge tx status\n *\n * @param startPollingForBridgeTxStatusArgs - The args to start polling for the bridge tx status\n */\n startPollingForBridgeTxStatus = (\n startPollingForBridgeTxStatusArgs: StartPollingForBridgeTxStatusArgsSerialized,\n ) => {\n const {\n bridgeTxMeta,\n statusRequest,\n quoteResponse,\n startTime,\n slippagePercentage,\n initialDestAssetBalance,\n targetContractAddress,\n } = startPollingForBridgeTxStatusArgs;\n const accountAddress = this.#getMultichainSelectedAccountAddress();\n // Write all non-status fields to state so we can reference the quote in Activity list without the Bridge API\n // We know it's in progress but not the exact status yet\n const txHistoryItem = {\n txMetaId: bridgeTxMeta.id,\n quote: quoteResponse.quote,\n startTime,\n estimatedProcessingTimeInSeconds:\n quoteResponse.estimatedProcessingTimeInSeconds,\n slippagePercentage,\n pricingData: {\n amountSent: quoteResponse.sentAmount.amount,\n amountSentInUsd: quoteResponse.sentAmount.usd ?? undefined,\n quotedGasInUsd: quoteResponse.gasFee.usd ?? undefined,\n quotedReturnInUsd: quoteResponse.toTokenAmount.usd ?? undefined,\n },\n initialDestAssetBalance,\n targetContractAddress,\n account: accountAddress,\n status: {\n // We always have a PENDING status when we start polling for a tx, don't need the Bridge API for that\n // Also we know the bare minimum fields for status at this point in time\n status: StatusTypes.PENDING,\n srcChain: {\n chainId: statusRequest.srcChainId,\n txHash: statusRequest.srcTxHash,\n },\n },\n hasApprovalTx: Boolean(quoteResponse.approval),\n };\n this.update((state) => {\n // Use the txMeta.id as the key so we can reference the txMeta in TransactionController\n state.txHistory[bridgeTxMeta.id] = txHistoryItem;\n });\n\n this.#pollingTokensByTxMetaId[bridgeTxMeta.id] = this.startPolling({\n bridgeTxMetaId: bridgeTxMeta.id,\n });\n };\n\n // This will be called after you call this.startPolling()\n // The args passed in are the args you passed in to startPolling()\n _executePoll = async (pollingInput: BridgeStatusPollingInput) => {\n await this.#fetchBridgeTxStatus(pollingInput);\n };\n\n #getMultichainSelectedAccount() {\n return this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n }\n\n #getMultichainSelectedAccountAddress() {\n return this.#getMultichainSelectedAccount()?.address ?? '';\n }\n\n readonly #fetchBridgeTxStatus = async ({\n bridgeTxMetaId,\n }: FetchBridgeTxStatusArgs) => {\n const { txHistory } = this.state;\n\n try {\n // We try here because we receive 500 errors from Bridge API if we try to fetch immediately after submitting the source tx\n // Oddly mostly happens on Optimism, never on Arbitrum. By the 2nd fetch, the Bridge API responds properly.\n // Also srcTxHash may not be available immediately for STX, so we don't want to fetch in those cases\n const historyItem = txHistory[bridgeTxMetaId];\n const srcTxHash = this.#getSrcTxHash(bridgeTxMetaId);\n if (!srcTxHash) {\n return;\n }\n\n this.#updateSrcTxHash(bridgeTxMetaId, srcTxHash);\n\n const statusRequest = getStatusRequestWithSrcTxHash(\n historyItem.quote,\n srcTxHash,\n );\n const status = await fetchBridgeTxStatus(\n statusRequest,\n this.#clientId,\n this.#fetchFn,\n this.#config.customBridgeApiBaseUrl,\n );\n const newBridgeHistoryItem = {\n ...historyItem,\n status,\n completionTime:\n status.status === StatusTypes.COMPLETE ||\n status.status === StatusTypes.FAILED\n ? Date.now()\n : undefined, // TODO make this more accurate by looking up dest txHash block time\n };\n\n // No need to purge these on network change or account change, TransactionController does not purge either.\n // TODO In theory we can skip checking status if it's not the current account/network\n // we need to keep track of the account that this is associated with as well so that we don't show it in Activity list for other accounts\n // First stab at this will not stop polling when you are on a different account\n this.update((state) => {\n state.txHistory[bridgeTxMetaId] = newBridgeHistoryItem;\n });\n\n const pollingToken = this.#pollingTokensByTxMetaId[bridgeTxMetaId];\n\n if (\n (status.status === StatusTypes.COMPLETE ||\n status.status === StatusTypes.FAILED) &&\n pollingToken\n ) {\n this.stopPollingByPollingToken(pollingToken);\n\n if (status.status === StatusTypes.COMPLETE) {\n this.messagingSystem.publish(\n `${BRIDGE_STATUS_CONTROLLER_NAME}:bridgeTransactionComplete`,\n { bridgeHistoryItem: newBridgeHistoryItem },\n );\n }\n if (status.status === StatusTypes.FAILED) {\n this.messagingSystem.publish(\n `${BRIDGE_STATUS_CONTROLLER_NAME}:bridgeTransactionFailed`,\n { bridgeHistoryItem: newBridgeHistoryItem },\n );\n }\n }\n } catch (e) {\n console.log('Failed to fetch bridge tx status', e);\n }\n };\n\n readonly #getSrcTxHash = (bridgeTxMetaId: string): string | undefined => {\n const { txHistory } = this.state;\n // Prefer the srcTxHash from bridgeStatusState so we don't have to l ook up in TransactionController\n // But it is possible to have bridgeHistoryItem in state without the srcTxHash yet when it is an STX\n const srcTxHash = txHistory[bridgeTxMetaId].status.srcChain.txHash;\n\n if (srcTxHash) {\n return srcTxHash;\n }\n\n // Look up in TransactionController if txMeta has been updated with the srcTxHash\n const txControllerState = this.messagingSystem.call(\n 'TransactionController:getState',\n );\n const txMeta = txControllerState.transactions.find(\n (tx) => tx.id === bridgeTxMetaId,\n );\n return txMeta?.hash;\n };\n\n readonly #updateSrcTxHash = (bridgeTxMetaId: string, srcTxHash: string) => {\n const { txHistory } = this.state;\n if (txHistory[bridgeTxMetaId].status.srcChain.txHash) {\n return;\n }\n\n this.update((state) => {\n state.txHistory[bridgeTxMetaId].status.srcChain.txHash = srcTxHash;\n });\n };\n\n // Wipes the bridge status for the given address and chainId\n // Will match only source chainId to the selectedChainId\n readonly #wipeBridgeStatusByChainId = (\n address: string,\n selectedChainId: Hex,\n ) => {\n const sourceTxMetaIdsToDelete = Object.keys(this.state.txHistory).filter(\n (txMetaId) => {\n const bridgeHistoryItem = this.state.txHistory[txMetaId];\n\n const hexSourceChainId = numberToHex(\n bridgeHistoryItem.quote.srcChainId,\n );\n\n return (\n bridgeHistoryItem.account === address &&\n hexSourceChainId === selectedChainId\n );\n },\n );\n\n sourceTxMetaIdsToDelete.forEach((sourceTxMetaId) => {\n const pollingToken = this.#pollingTokensByTxMetaId[sourceTxMetaId];\n\n if (pollingToken) {\n this.stopPollingByPollingToken(\n this.#pollingTokensByTxMetaId[sourceTxMetaId],\n );\n }\n });\n\n this.update((state) => {\n state.txHistory = sourceTxMetaIdsToDelete.reduce(\n (acc, sourceTxMetaId) => {\n delete acc[sourceTxMetaId];\n return acc;\n },\n state.txHistory,\n );\n });\n };\n\n /**\n * Submits a solana swap or bridge transaction using the snap controller\n *\n * @param trade - The trade data to confirm\n * @param quoteResponse - The quote response\n * @param quoteResponse.quote - The quote\n * @returns The transaction meta\n */\n readonly #handleSolanaTx = async (\n trade: string,\n quoteResponse: Omit<QuoteResponse<string>, 'approval' | 'trade'> &\n QuoteMetadata,\n ) => {\n const selectedAccount = this.#getMultichainSelectedAccount();\n if (!selectedAccount) {\n throw new Error(\n 'Failed to submit cross-chain swap transaction: undefined multichain account',\n );\n }\n if (\n !selectedAccount.metadata?.snap?.id ||\n !selectedAccount.options?.scope\n ) {\n throw new Error(\n 'Failed to submit cross-chain swap transaction: undefined snap id or scope',\n );\n }\n /**\n * Submit the transaction to the snap using the keyring rpc method\n * This adds an approval tx to the ApprovalsController in the background\n * The client needs to handle the approval tx by redirecting to the confirmation page with the approvalTxId in the URL\n */\n const keyringReqId = uuid();\n const snapRequestId = uuid();\n const keyringResponse = await this.messagingSystem.call(\n 'SnapController:handleRequest',\n {\n origin: 'metamask',\n snapId: selectedAccount.metadata.snap.id as never,\n handler: 'onKeyringRequest' as never,\n request: {\n id: keyringReqId,\n jsonrpc: '2.0',\n method: 'keyring_submitRequest',\n params: {\n request: {\n params: {\n account: { address: selectedAccount.address },\n transaction: trade,\n scope: selectedAccount.options.scope,\n },\n method: 'signAndSendTransaction',\n },\n id: snapRequestId,\n account: selectedAccount.id,\n scope: selectedAccount.options.scope,\n },\n },\n },\n );\n\n // The extension client actually redirects before it can do anytyhing with this meta\n const txMeta = handleSolanaTxResponse(\n keyringResponse as never, // This is ok bc the snap response can be different types\n quoteResponse,\n selectedAccount.metadata.snap.id,\n selectedAccount.address,\n );\n\n // TODO remove this eventually, just returning it now to match extension behavior\n // OR if the snap can propagate the snapRequestId or keyringReqId to the ApprovalsControlle, this can return the approvalTxId instead and clients won't need to subscribe to the ApprovalsController state to redirect\n return {\n ...txMeta,\n keyringReqId,\n snapRequestId,\n };\n };\n\n readonly #shouldUseSmartTransactions = (isStxEnabledOnClient: boolean) => {\n const isUserOptedInToStx = this.messagingSystem.call(\n 'PreferencesController:getState',\n ).smartTransactionsOptInStatus;\n // User has no opt in status, use default value from client\n return (\n (isUserOptedInToStx ?? this.#config.smartTransactionsEnabledByDefault) &&\n isStxEnabledOnClient\n );\n };\n\n /**\n * Submits an EVM transaction to the TransactionController\n *\n * @param transactionType - The type of transaction to submit\n * @param trade - The trade data to confirm\n * @param quoteResponse - The quote response\n * @param quoteResponse.quote - The quote\n * @param approvalTxId - The tx id of the approval tx\n * @param shouldWaitForHash - Whether to wait for the hash of the transaction\n * @returns The transaction meta\n */\n readonly #handleEvmTransaction = async (\n transactionType: TransactionType,\n trade: TxData,\n quoteResponse: Omit<QuoteResponse, 'approval' | 'trade'> & QuoteMetadata,\n approvalTxId?: string,\n shouldWaitForHash = true,\n ): Promise<TransactionMeta | undefined> => {\n const actionId = generateActionId().toString();\n\n const selectedAccount = this.messagingSystem.call(\n 'AccountsController:getAccountByAddress',\n trade.from,\n );\n if (!selectedAccount) {\n throw new Error(\n 'Failed to submit cross-chain swap transaction: unknown account in trade data',\n );\n }\n const hexChainId = formatChainIdToHex(trade.chainId);\n const networkClientId = this.messagingSystem.call(\n 'NetworkController:findNetworkClientIdByChainId',\n hexChainId,\n );\n\n const requestOptions = {\n actionId,\n networkClientId,\n requireApproval: false,\n type: transactionType,\n origin: 'metamask',\n };\n const transactionParams = {\n ...trade,\n chainId: hexChainId,\n gasLimit: trade.gasLimit?.toString(),\n gas: trade.gasLimit?.toString(),\n };\n const transactionParamsWithMaxGas: TransactionParams = {\n ...transactionParams,\n ...(await this.#calculateGasFees(\n transactionParams,\n networkClientId,\n hexChainId,\n )),\n };\n\n let result:\n | Awaited<ReturnType<TransactionController['addTransaction']>>['result']\n | undefined;\n let transactionMeta: TransactionMeta | undefined;\n\n const isSmartContractAccount =\n selectedAccount.type === EthAccountType.Erc4337;\n if (isSmartContractAccount) {\n const userOperationResult = await this.#addUserOperationFromTransactionFn(\n transactionParamsWithMaxGas,\n requestOptions,\n );\n\n // TODO return hash and txMeta from UserOperationController.addUserOperationFromTransaction\n transactionMeta = {\n id: userOperationResult.id,\n } as never;\n // result = userOperationResult.hash();\n } else {\n const addTransactionResult = await this.#addTransactionFn(\n transactionParamsWithMaxGas,\n requestOptions,\n );\n result = addTransactionResult.result;\n transactionMeta = addTransactionResult.transactionMeta;\n }\n\n // Note that updateTransaction doesn't actually error if you add fields that don't conform the to the txMeta type\n // they will be there at runtime, but you just don't get any type safety checks on them\n const completeTxMeta = {\n ...transactionMeta,\n ...getTxMetaFields(quoteResponse, approvalTxId),\n };\n // TODO why is this needed? Can we skip update and directly pass txMetaFields to TransactionController.addTransctin call\n // const fieldsToAddToTxMeta = getTxMetaFields(quoteResponse, approvalTxId);\n // dispatch(updateTransaction(completeTxMeta);\n\n if (shouldWaitForHash) {\n return await this.#waitForHashAndReturnFinalTxMeta(result);\n }\n\n return completeTxMeta;\n };\n\n readonly #waitForHashAndReturnFinalTxMeta = async (\n hashPromise?: Awaited<\n ReturnType<TransactionController['addTransaction']>\n >['result'],\n ) => {\n const transactionHash = await hashPromise;\n const finalTransactionMeta = this.messagingSystem\n .call('TransactionController:getState')\n .transactions.find((tx: TransactionMeta) => tx.hash === transactionHash);\n return finalTransactionMeta;\n };\n\n /**\n * Submits a smart transaction\n *\n * @param trade - The trade data to confirm\n * @param quoteResponse - The quote response\n * @param quoteResponse.quote - The quote\n * @param approvalTxId - The tx id of the approval tx\n * @returns The transaction meta\n */\n readonly #handleSmartTransaction = async (\n trade: TxData,\n quoteResponse: Omit<QuoteResponse, 'approval' | 'trade'> & QuoteMetadata,\n approvalTxId?: string,\n ) => {\n return await this.#handleEvmTransaction(\n TransactionType.bridge,\n trade,\n quoteResponse,\n approvalTxId,\n false, // Set to false to indicate we don't want to wait for hash\n );\n };\n\n // Only add tokens if the source or dest chain is an EVM chain bc non-evm tokens\n // are detected by the multichain asset controllers\n readonly #addTokens = (asset: BridgeAsset) => {\n // Return early if the asset chain is native or if asset is in the solana chain\n if (isNativeAddress(asset.address) || isSolanaChainId(asset.chainId)) {\n return;\n }\n this.messagingSystem\n .call(\n 'TokensController:addDetectedTokens',\n [\n {\n address: asset.address,\n decimals: asset.decimals,\n image: asset.iconUrl,\n name: asset.name,\n symbol: asset.symbol,\n },\n ],\n {\n chainId: formatChainIdToHex(asset.chainId),\n selectedAddress: this.#getMultichainSelectedAccountAddress(),\n },\n )\n .catch(() => {\n // Ignore errors\n });\n };\n}\n"]}
|
package/dist/constants.cjs
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE = exports.BRIDGE_STATUS_CONTROLLER_NAME = exports.REFRESH_INTERVAL_MS = void 0;
|
3
|
+
exports.LINEA_DELAY_MS = exports.BRIDGE_PROD_API_BASE_URL = exports.DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE = exports.BRIDGE_STATUS_CONTROLLER_NAME = exports.REFRESH_INTERVAL_MS = void 0;
|
4
4
|
exports.REFRESH_INTERVAL_MS = 10 * 1000;
|
5
5
|
exports.BRIDGE_STATUS_CONTROLLER_NAME = 'BridgeStatusController';
|
6
6
|
exports.DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE = {
|
7
7
|
txHistory: {},
|
8
8
|
};
|
9
|
+
exports.BRIDGE_PROD_API_BASE_URL = 'https://bridge.api.cx.metamask.io';
|
10
|
+
exports.LINEA_DELAY_MS = 5000;
|
9
11
|
//# sourceMappingURL=constants.cjs.map
|
package/dist/constants.cjs.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"constants.cjs","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAEa,QAAA,mBAAmB,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhC,QAAA,6BAA6B,GAAG,wBAAwB,CAAC;AAEzD,QAAA,sCAAsC,GACjD;IACE,SAAS,EAAE,EAAE;CACd,CAAC","sourcesContent":["import type { BridgeStatusControllerState } from './types';\n\nexport const REFRESH_INTERVAL_MS = 10 * 1000;\n\nexport const BRIDGE_STATUS_CONTROLLER_NAME = 'BridgeStatusController';\n\nexport const DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE: BridgeStatusControllerState =\n {\n txHistory: {},\n };\n"]}
|
1
|
+
{"version":3,"file":"constants.cjs","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAEa,QAAA,mBAAmB,GAAG,EAAE,GAAG,IAAI,CAAC;AAEhC,QAAA,6BAA6B,GAAG,wBAAwB,CAAC;AAEzD,QAAA,sCAAsC,GACjD;IACE,SAAS,EAAE,EAAE;CACd,CAAC;AAES,QAAA,wBAAwB,GAAG,mCAAmC,CAAC;AAE/D,QAAA,cAAc,GAAG,IAAI,CAAC","sourcesContent":["import type { BridgeStatusControllerState } from './types';\n\nexport const REFRESH_INTERVAL_MS = 10 * 1000;\n\nexport const BRIDGE_STATUS_CONTROLLER_NAME = 'BridgeStatusController';\n\nexport const DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE: BridgeStatusControllerState =\n {\n txHistory: {},\n };\n\nexport const BRIDGE_PROD_API_BASE_URL = 'https://bridge.api.cx.metamask.io';\n\nexport const LINEA_DELAY_MS = 5000;\n"]}
|
package/dist/constants.d.cts
CHANGED
@@ -2,4 +2,6 @@ import type { BridgeStatusControllerState } from "./types.cjs";
|
|
2
2
|
export declare const REFRESH_INTERVAL_MS: number;
|
3
3
|
export declare const BRIDGE_STATUS_CONTROLLER_NAME = "BridgeStatusController";
|
4
4
|
export declare const DEFAULT_BRIDGE_STATUS_CONTROLLER_STATE: BridgeStatusControllerState;
|
5
|
+
export declare const BRIDGE_PROD_API_BASE_URL = "https://bridge.api.cx.metamask.io";
|
6
|
+
export declare const LINEA_DELAY_MS = 5000;
|
5
7
|
//# sourceMappingURL=constants.d.cts.map
|