@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.
Files changed (130) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/dist/bridge-status-controller.cjs +115 -354
  3. package/dist/bridge-status-controller.cjs.map +1 -1
  4. package/dist/bridge-status-controller.d.cts +3 -5
  5. package/dist/bridge-status-controller.d.cts.map +1 -1
  6. package/dist/bridge-status-controller.d.mts +3 -5
  7. package/dist/bridge-status-controller.d.mts.map +1 -1
  8. package/dist/bridge-status-controller.intent.cjs +12 -25
  9. package/dist/bridge-status-controller.intent.cjs.map +1 -1
  10. package/dist/bridge-status-controller.intent.d.cts +3 -14
  11. package/dist/bridge-status-controller.intent.d.cts.map +1 -1
  12. package/dist/bridge-status-controller.intent.d.mts +3 -14
  13. package/dist/bridge-status-controller.intent.d.mts.map +1 -1
  14. package/dist/bridge-status-controller.intent.mjs +12 -25
  15. package/dist/bridge-status-controller.intent.mjs.map +1 -1
  16. package/dist/bridge-status-controller.mjs +118 -357
  17. package/dist/bridge-status-controller.mjs.map +1 -1
  18. package/dist/index.cjs +1 -3
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +0 -1
  21. package/dist/index.d.cts.map +1 -1
  22. package/dist/index.d.mts +0 -1
  23. package/dist/index.d.mts.map +1 -1
  24. package/dist/index.mjs +0 -1
  25. package/dist/index.mjs.map +1 -1
  26. package/dist/types.cjs.map +1 -1
  27. package/dist/types.d.cts +11 -5
  28. package/dist/types.d.cts.map +1 -1
  29. package/dist/types.d.mts +11 -5
  30. package/dist/types.d.mts.map +1 -1
  31. package/dist/types.mjs.map +1 -1
  32. package/dist/utils/accounts.cjs +8 -0
  33. package/dist/utils/accounts.cjs.map +1 -0
  34. package/dist/utils/accounts.d.cts +36 -0
  35. package/dist/utils/accounts.d.cts.map +1 -0
  36. package/dist/utils/accounts.d.mts +36 -0
  37. package/dist/utils/accounts.d.mts.map +1 -0
  38. package/dist/utils/accounts.mjs +4 -0
  39. package/dist/utils/accounts.mjs.map +1 -0
  40. package/dist/utils/authentication.cjs +15 -0
  41. package/dist/utils/authentication.cjs.map +1 -0
  42. package/dist/utils/authentication.d.cts +3 -0
  43. package/dist/utils/authentication.d.cts.map +1 -0
  44. package/dist/utils/authentication.d.mts +3 -0
  45. package/dist/utils/authentication.d.mts.map +1 -0
  46. package/dist/utils/authentication.mjs +11 -0
  47. package/dist/utils/authentication.mjs.map +1 -0
  48. package/dist/utils/bridge-status.cjs +17 -1
  49. package/dist/utils/bridge-status.cjs.map +1 -1
  50. package/dist/utils/bridge-status.d.cts +8 -2
  51. package/dist/utils/bridge-status.d.cts.map +1 -1
  52. package/dist/utils/bridge-status.d.mts +8 -2
  53. package/dist/utils/bridge-status.d.mts.map +1 -1
  54. package/dist/utils/bridge-status.mjs +15 -0
  55. package/dist/utils/bridge-status.mjs.map +1 -1
  56. package/dist/utils/bridge.cjs +16 -0
  57. package/dist/utils/bridge.cjs.map +1 -0
  58. package/dist/utils/bridge.d.cts +10 -0
  59. package/dist/utils/bridge.d.cts.map +1 -0
  60. package/dist/utils/bridge.d.mts +10 -0
  61. package/dist/utils/bridge.d.mts.map +1 -0
  62. package/dist/utils/bridge.mjs +11 -0
  63. package/dist/utils/bridge.mjs.map +1 -0
  64. package/dist/utils/gas.cjs +1 -61
  65. package/dist/utils/gas.cjs.map +1 -1
  66. package/dist/utils/gas.d.cts +3 -26
  67. package/dist/utils/gas.d.cts.map +1 -1
  68. package/dist/utils/gas.d.mts +3 -26
  69. package/dist/utils/gas.d.mts.map +1 -1
  70. package/dist/utils/gas.mjs +0 -58
  71. package/dist/utils/gas.mjs.map +1 -1
  72. package/dist/utils/history.cjs +98 -0
  73. package/dist/utils/history.cjs.map +1 -0
  74. package/dist/utils/history.d.cts +22 -0
  75. package/dist/utils/history.d.cts.map +1 -0
  76. package/dist/utils/history.d.mts +22 -0
  77. package/dist/utils/history.d.mts.map +1 -0
  78. package/dist/utils/history.mjs +91 -0
  79. package/dist/utils/history.mjs.map +1 -0
  80. package/dist/utils/intent-api.cjs +41 -26
  81. package/dist/utils/intent-api.cjs.map +1 -1
  82. package/dist/utils/intent-api.d.cts +16 -3
  83. package/dist/utils/intent-api.d.cts.map +1 -1
  84. package/dist/utils/intent-api.d.mts +16 -3
  85. package/dist/utils/intent-api.d.mts.map +1 -1
  86. package/dist/utils/intent-api.mjs +38 -25
  87. package/dist/utils/intent-api.mjs.map +1 -1
  88. package/dist/utils/keyring.cjs +12 -0
  89. package/dist/utils/keyring.cjs.map +1 -0
  90. package/dist/utils/keyring.d.cts +8 -0
  91. package/dist/utils/keyring.d.cts.map +1 -0
  92. package/dist/utils/keyring.d.mts +8 -0
  93. package/dist/utils/keyring.d.mts.map +1 -0
  94. package/dist/utils/keyring.mjs +8 -0
  95. package/dist/utils/keyring.mjs.map +1 -0
  96. package/dist/utils/network.cjs +17 -0
  97. package/dist/utils/network.cjs.map +1 -0
  98. package/dist/utils/network.d.cts +5 -0
  99. package/dist/utils/network.d.cts.map +1 -0
  100. package/dist/utils/network.d.mts +5 -0
  101. package/dist/utils/network.d.mts.map +1 -0
  102. package/dist/utils/network.mjs +12 -0
  103. package/dist/utils/network.mjs.map +1 -0
  104. package/dist/utils/snaps.cjs +146 -1
  105. package/dist/utils/snaps.cjs.map +1 -1
  106. package/dist/utils/snaps.d.cts +48 -0
  107. package/dist/utils/snaps.d.cts.map +1 -1
  108. package/dist/utils/snaps.d.mts +48 -0
  109. package/dist/utils/snaps.d.mts.map +1 -1
  110. package/dist/utils/snaps.mjs +141 -0
  111. package/dist/utils/snaps.mjs.map +1 -1
  112. package/dist/utils/trace.cjs +31 -0
  113. package/dist/utils/trace.cjs.map +1 -0
  114. package/dist/utils/trace.d.cts +17 -0
  115. package/dist/utils/trace.d.cts.map +1 -0
  116. package/dist/utils/trace.d.mts +17 -0
  117. package/dist/utils/trace.d.mts.map +1 -0
  118. package/dist/utils/trace.mjs +26 -0
  119. package/dist/utils/trace.mjs.map +1 -0
  120. package/dist/utils/transaction.cjs +239 -184
  121. package/dist/utils/transaction.cjs.map +1 -1
  122. package/dist/utils/transaction.d.cts +85 -236
  123. package/dist/utils/transaction.d.cts.map +1 -1
  124. package/dist/utils/transaction.d.mts +85 -236
  125. package/dist/utils/transaction.d.mts.map +1 -1
  126. package/dist/utils/transaction.mjs +226 -176
  127. package/dist/utils/transaction.mjs.map +1 -1
  128. package/dist/utils/validators.d.cts +2 -2
  129. package/dist/utils/validators.d.mts +2 -2
  130. package/package.json +3 -3
@@ -1,123 +1,144 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getIntentFromQuote = exports.getHistoryKey = exports.findAndUpdateTransactionsInBatch = exports.getAddTransactionBatchParams = exports.toBatchTxParams = exports.rekeyHistoryItemInState = exports.waitForTxConfirmation = exports.getClientRequest = exports.handleMobileHardwareWalletDelay = exports.handleApprovalDelay = exports.handleNonEvmTxResponse = exports.getTxMetaFields = exports.getStatusRequestParams = exports.generateActionId = void 0;
3
+ exports.submitEvmTransaction = exports.addTransactionBatch = exports.findAndUpdateTransactionsInBatch = exports.getAddTransactionBatchParams = exports.toBatchTxParams = exports.waitForTxConfirmation = exports.handleMobileHardwareWalletDelay = exports.handleApprovalDelay = exports.addSyntheticTransaction = exports.generateActionId = exports.addTransaction = exports.checkIsDelegatedAccount = exports.updateTransaction = exports.getTransactionMetaByHash = exports.getTransactionMetaById = exports.getTransactions = exports.calculateGasFees = exports.getTxGasEstimates = exports.getGasFeeEstimates = void 0;
4
+ /* eslint-disable @typescript-eslint/explicit-function-return-type */
4
5
  const bridge_controller_1 = require("@metamask/bridge-controller");
5
6
  const controller_utils_1 = require("@metamask/controller-utils");
6
7
  const transaction_controller_1 = require("@metamask/transaction-controller");
7
8
  const utils_1 = require("@metamask/utils");
8
- const uuid_1 = require("uuid");
9
- const gas_1 = require("./gas.cjs");
10
- const snaps_1 = require("./snaps.cjs");
9
+ const bignumber_js_1 = require("bignumber.js");
10
+ const accounts_1 = require("./accounts.cjs");
11
+ const network_1 = require("./network.cjs");
11
12
  const constants_1 = require("../constants.cjs");
12
- const generateActionId = () => (Date.now() + Math.random()).toString();
13
- exports.generateActionId = generateActionId;
14
- const getStatusRequestParams = (quoteResponse) => {
13
+ const getGasFeeEstimates = async (messenger, args) => {
14
+ const { estimates } = await messenger.call('TransactionController:estimateGasFee', args);
15
+ if (bridge_controller_1.BRIDGE_PREFERRED_GAS_ESTIMATE in estimates &&
16
+ typeof estimates[bridge_controller_1.BRIDGE_PREFERRED_GAS_ESTIMATE] === 'object' &&
17
+ 'maxFeePerGas' in estimates[bridge_controller_1.BRIDGE_PREFERRED_GAS_ESTIMATE] &&
18
+ 'maxPriorityFeePerGas' in estimates[bridge_controller_1.BRIDGE_PREFERRED_GAS_ESTIMATE]) {
19
+ return estimates[bridge_controller_1.BRIDGE_PREFERRED_GAS_ESTIMATE];
20
+ }
21
+ return {};
22
+ };
23
+ exports.getGasFeeEstimates = getGasFeeEstimates;
24
+ /**
25
+ * Get the gas fee estimates for a transaction
26
+ *
27
+ * @param messenger - The messenger for the gas fee estimates
28
+ * @param estimateGasFeeParams - The parameters for the {@link TransactionController.estimateGasFee} method
29
+
30
+ * @returns The gas fee estimates for the transaction
31
+ */
32
+ const getTxGasEstimates = async (messenger, estimateGasFeeParams) => {
33
+ const { gasFeeEstimates } = messenger.call('GasFeeController:getState');
34
+ const estimatedBaseFee = 'estimatedBaseFee' in gasFeeEstimates
35
+ ? gasFeeEstimates.estimatedBaseFee
36
+ : '0';
37
+ // Get transaction's 1559 gas fee estimates
38
+ const { maxFeePerGas, maxPriorityFeePerGas } = await (0, exports.getGasFeeEstimates)(messenger, estimateGasFeeParams);
39
+ /**
40
+ * @deprecated this is unused
41
+ */
42
+ const baseAndPriorityFeePerGas = maxPriorityFeePerGas
43
+ ? new bignumber_js_1.BigNumber(estimatedBaseFee, 10)
44
+ .times(10 ** 9)
45
+ .plus(maxPriorityFeePerGas, 16)
46
+ : undefined;
15
47
  return {
16
- bridgeId: quoteResponse.quote.bridgeId,
17
- bridge: quoteResponse.quote.bridges[0],
18
- srcChainId: quoteResponse.quote.srcChainId,
19
- destChainId: quoteResponse.quote.destChainId,
20
- quote: quoteResponse.quote,
21
- refuel: Boolean(quoteResponse.quote.refuel),
48
+ baseAndPriorityFeePerGas,
49
+ maxFeePerGas,
50
+ maxPriorityFeePerGas,
22
51
  };
23
52
  };
24
- exports.getStatusRequestParams = getStatusRequestParams;
25
- const getTxMetaFields = (quoteResponse, approvalTxId) => {
26
- // Handle destination chain ID - should always be convertible for EVM destinations
27
- let destinationChainId;
28
- try {
29
- destinationChainId = (0, bridge_controller_1.formatChainIdToHex)(quoteResponse.quote.destChainId);
53
+ exports.getTxGasEstimates = getTxGasEstimates;
54
+ const calculateGasFees = async (skipGasFields, messenger, { chainId: _, gasLimit, ...trade }, networkClientId, chainId, txFee) => {
55
+ if (skipGasFields) {
56
+ return {};
30
57
  }
31
- catch {
32
- // Fallback for non-EVM destination (shouldn't happen for BTC->EVM)
33
- destinationChainId = '0x1'; // Default to mainnet
58
+ if (txFee) {
59
+ return { ...txFee, gas: gasLimit?.toString() };
34
60
  }
61
+ const transactionParams = {
62
+ ...trade,
63
+ gas: gasLimit?.toString(),
64
+ data: trade.data,
65
+ to: trade.to,
66
+ value: trade.value,
67
+ };
68
+ const { maxFeePerGas, maxPriorityFeePerGas } = await (0, exports.getTxGasEstimates)(messenger, {
69
+ transactionParams,
70
+ networkClientId,
71
+ chainId,
72
+ });
73
+ const maxGasLimit = (0, controller_utils_1.toHex)(transactionParams.gas ?? 0);
35
74
  return {
36
- destinationChainId,
37
- sourceTokenAmount: quoteResponse.quote.srcTokenAmount,
38
- sourceTokenSymbol: quoteResponse.quote.srcAsset.symbol,
39
- sourceTokenDecimals: quoteResponse.quote.srcAsset.decimals,
40
- sourceTokenAddress: quoteResponse.quote.srcAsset.address,
41
- destinationTokenAmount: quoteResponse.quote.destTokenAmount,
42
- destinationTokenSymbol: quoteResponse.quote.destAsset.symbol,
43
- destinationTokenDecimals: quoteResponse.quote.destAsset.decimals,
44
- destinationTokenAddress: quoteResponse.quote.destAsset.address,
45
- // chainId is now excluded from this function and handled by the caller
46
- approvalTxId,
47
- // this is the decimal (non atomic) amount (not USD value) of source token to swap
48
- swapTokenValue: quoteResponse.sentAmount.amount,
75
+ maxFeePerGas,
76
+ maxPriorityFeePerGas,
77
+ gas: maxGasLimit,
49
78
  };
50
79
  };
51
- exports.getTxMetaFields = getTxMetaFields;
52
- /**
53
- * Handles the response from non-EVM transaction submission
54
- * Works with the new unified ClientRequest:signAndSendTransaction interface
55
- * Supports Solana, Bitcoin, and other non-EVM chains
56
- *
57
- * @param snapResponse - The response from the snap after transaction submission
58
- * @param quoteResponse - The quote response containing trade details and metadata
59
- * @param selectedAccount - The selected account information
60
- * @returns The transaction metadata including non-EVM specific fields
61
- */
62
- const handleNonEvmTxResponse = (snapResponse, quoteResponse, selectedAccount) => {
63
- const selectedAccountAddress = selectedAccount.address;
64
- const snapId = selectedAccount.metadata.snap?.id;
65
- let hash;
66
- // Handle different response formats
67
- if (typeof snapResponse === 'string') {
68
- hash = snapResponse;
69
- }
70
- else if (snapResponse && typeof snapResponse === 'object') {
71
- // Check for new unified interface response format first
72
- if ('transactionId' in snapResponse && snapResponse.transactionId) {
73
- hash = snapResponse.transactionId;
74
- }
75
- else if ('result' in snapResponse &&
76
- snapResponse.result &&
77
- typeof snapResponse.result === 'object') {
78
- // Try to extract signature from common locations in response object
79
- hash =
80
- snapResponse.result.signature ||
81
- snapResponse.result.txid ||
82
- snapResponse.result.hash ||
83
- snapResponse.result.txHash;
84
- }
85
- else if ('signature' in snapResponse &&
86
- snapResponse.signature &&
87
- typeof snapResponse.signature === 'string') {
88
- hash = snapResponse.signature;
89
- }
90
- }
91
- const isBridgeTx = (0, bridge_controller_1.isCrossChain)(quoteResponse.quote.srcChainId, quoteResponse.quote.destChainId);
92
- let hexChainId;
80
+ exports.calculateGasFees = calculateGasFees;
81
+ const getTransactions = (messenger) => {
82
+ return messenger.call('TransactionController:getState').transactions ?? [];
83
+ };
84
+ exports.getTransactions = getTransactions;
85
+ const getTransactionMetaById = (messenger, txId) => {
86
+ return (0, exports.getTransactions)(messenger).find((tx) => tx.id === txId);
87
+ };
88
+ exports.getTransactionMetaById = getTransactionMetaById;
89
+ const getTransactionMetaByHash = (messenger, txHash) => {
90
+ return (0, exports.getTransactions)(messenger).find((tx) => tx.hash === txHash);
91
+ };
92
+ exports.getTransactionMetaByHash = getTransactionMetaByHash;
93
+ const updateTransaction = (messenger, txMeta, txMetaUpdates, note) => {
94
+ return messenger.call('TransactionController:updateTransaction', { ...txMeta, ...txMetaUpdates }, note);
95
+ };
96
+ exports.updateTransaction = updateTransaction;
97
+ const checkIsDelegatedAccount = async (messenger, fromAddress, chainIds) => {
93
98
  try {
94
- hexChainId = (0, bridge_controller_1.formatChainIdToHex)(quoteResponse.quote.srcChainId);
99
+ const atomicBatchSupport = await messenger.call('TransactionController:isAtomicBatchSupported', {
100
+ address: fromAddress,
101
+ chainIds,
102
+ });
103
+ return atomicBatchSupport.some((entry) => entry.isSupported && entry.delegationAddress);
95
104
  }
96
105
  catch {
97
- // TODO: Fix chain ID activity list handling for Bitcoin
98
- // Fallback to Ethereum mainnet for now
99
- hexChainId = '0x1';
106
+ return false;
100
107
  }
101
- // Extract the transaction data for storage
102
- const tradeData = (0, bridge_controller_1.extractTradeData)(quoteResponse.trade);
103
- // Create a transaction meta object with bridge-specific fields
104
- return {
105
- ...(0, exports.getTxMetaFields)(quoteResponse),
106
- time: Date.now(),
107
- id: hash ?? (0, uuid_1.v4)(),
108
- chainId: hexChainId,
109
- networkClientId: snapId ?? hexChainId,
110
- txParams: { from: selectedAccountAddress, data: tradeData },
111
- type: isBridgeTx ? transaction_controller_1.TransactionType.bridge : transaction_controller_1.TransactionType.swap,
112
- status: transaction_controller_1.TransactionStatus.submitted,
113
- hash, // Add the transaction signature as hash
114
- origin: snapId,
115
- // Add an explicit flag to mark this as a non-EVM transaction
116
- isSolana: true, // TODO deprecate this and use chainId to detect non-EVM chains
117
- isBridgeTx,
118
- };
119
108
  };
120
- exports.handleNonEvmTxResponse = handleNonEvmTxResponse;
109
+ exports.checkIsDelegatedAccount = checkIsDelegatedAccount;
110
+ const waitForHashAndReturnFinalTxMeta = async (messenger, hashPromise) => {
111
+ const txHash = await hashPromise;
112
+ const finalTransactionMeta = (0, exports.getTransactionMetaByHash)(messenger, txHash);
113
+ if (!finalTransactionMeta) {
114
+ throw new Error('Failed to submit cross-chain swap tx: txMeta for txHash was not found');
115
+ }
116
+ return finalTransactionMeta;
117
+ };
118
+ const addTransaction = async (messenger, ...args) => {
119
+ const { result } = await messenger.call('TransactionController:addTransaction', ...args);
120
+ return await waitForHashAndReturnFinalTxMeta(messenger, result);
121
+ };
122
+ exports.addTransaction = addTransaction;
123
+ const generateActionId = () => (Date.now() + Math.random()).toString();
124
+ exports.generateActionId = generateActionId;
125
+ /**
126
+ * Adds a synthetic transaction to the TransactionController to display pending intent orders in the UI
127
+ *
128
+ * @param messenger - The messenger to use for the transaction
129
+ * @param args - The arguments for the transaction
130
+ * @returns The transaction meta
131
+ */
132
+ const addSyntheticTransaction = async (messenger, ...args) => {
133
+ const { transactionMeta } = await messenger.call('TransactionController:addTransaction', args[0], {
134
+ origin: 'metamask',
135
+ actionId: (0, exports.generateActionId)(),
136
+ isStateOnly: true,
137
+ ...args[1],
138
+ });
139
+ return transactionMeta;
140
+ };
141
+ exports.addSyntheticTransaction = addSyntheticTransaction;
121
142
  const handleApprovalDelay = async (srcChainId) => {
122
143
  if ([bridge_controller_1.ChainId.LINEA, bridge_controller_1.ChainId.BASE].includes(srcChainId)) {
123
144
  const debugLog = (0, utils_1.createProjectLogger)('bridge');
@@ -142,33 +163,20 @@ const handleMobileHardwareWalletDelay = async (requireApproval) => {
142
163
  };
143
164
  exports.handleMobileHardwareWalletDelay = handleMobileHardwareWalletDelay;
144
165
  /**
145
- * Creates a request to sign and send a transaction for non-EVM chains
146
- * Uses the new unified ClientRequest:signAndSendTransaction interface
166
+ * Waits until a given transaction (by id) reaches confirmed/finalized status or fails/times out.
147
167
  *
148
- * @param trade - The trade data
149
- * @param srcChainId - The source chain ID
150
- * @param selectedAccount - The selected account information
151
- * @returns The snap request object for signing and sending transaction
168
+ * @deprecated use addTransaction util
169
+ * @param messenger - the BridgeStatusControllerMessenger
170
+ * @param txId - the transaction ID
171
+ * @param options - the options for the timeout and poll
172
+ * @param options.timeoutMs - the timeout in milliseconds
173
+ * @param options.pollMs - the poll interval in milliseconds
174
+ * @returns the transaction meta
152
175
  */
153
- const getClientRequest = (trade, srcChainId, selectedAccount) => {
154
- const scope = (0, bridge_controller_1.formatChainIdToCaip)(srcChainId);
155
- const transactionData = (0, bridge_controller_1.extractTradeData)(trade);
156
- // Tron trades need the visible flag and contract type to be included in the request options
157
- const options = (0, bridge_controller_1.isTronTrade)(trade)
158
- ? {
159
- visible: trade.visible,
160
- type: trade.raw_data?.contract?.[0]?.type,
161
- }
162
- : undefined;
163
- // Use the new unified interface
164
- return (0, snaps_1.createClientTransactionRequest)(selectedAccount.metadata.snap?.id, transactionData, scope, selectedAccount.id, options);
165
- };
166
- exports.getClientRequest = getClientRequest;
167
176
  const waitForTxConfirmation = async (messenger, txId, { timeoutMs = 5 * 60000, pollMs = 3000, } = {}) => {
168
177
  const start = Date.now();
169
178
  while (true) {
170
- const { transactions } = messenger.call('TransactionController:getState');
171
- const meta = transactions.find((tx) => tx.id === txId);
179
+ const meta = (0, exports.getTransactionMetaById)(messenger, txId);
172
180
  if (meta) {
173
181
  if (meta.status === transaction_controller_1.TransactionStatus.confirmed) {
174
182
  return meta;
@@ -186,27 +194,6 @@ const waitForTxConfirmation = async (messenger, txId, { timeoutMs = 5 * 60000, p
186
194
  }
187
195
  };
188
196
  exports.waitForTxConfirmation = waitForTxConfirmation;
189
- const rekeyHistoryItemInState = (state, actionId, txMeta) => {
190
- const historyItem = state.txHistory[actionId];
191
- if (!historyItem) {
192
- return false;
193
- }
194
- state.txHistory[txMeta.id] = {
195
- ...historyItem,
196
- txMetaId: txMeta.id,
197
- originalTransactionId: historyItem.originalTransactionId ?? txMeta.id,
198
- status: {
199
- ...historyItem.status,
200
- srcChain: {
201
- ...historyItem.status.srcChain,
202
- txHash: txMeta.hash ?? historyItem.status.srcChain?.txHash,
203
- },
204
- },
205
- };
206
- delete state.txHistory[actionId];
207
- return true;
208
- };
209
- exports.rekeyHistoryItemInState = rekeyHistoryItemInState;
210
197
  const toBatchTxParams = (skipGasFields, { chainId, gasLimit, ...trade }, { maxFeePerGas, maxPriorityFeePerGas, gas, }) => {
211
198
  const params = {
212
199
  ...trade,
@@ -225,23 +212,28 @@ const toBatchTxParams = (skipGasFields, { chainId, gasLimit, ...trade }, { maxFe
225
212
  };
226
213
  };
227
214
  exports.toBatchTxParams = toBatchTxParams;
228
- const getAddTransactionBatchParams = async ({ messenger, isBridgeTx, approval, resetApproval, trade, quoteResponse: { quote: { feeData: { txFee }, gasIncluded, gasIncluded7702, gasSponsored, }, sentAmount, toTokenAmount, }, requireApproval = false, isDelegatedAccount = false, estimateGasFeeFn, }) => {
215
+ const getAddTransactionBatchParams = async ({ messenger, isBridgeTx, approval, resetApproval, trade, quoteResponse: { quote: { feeData: { txFee }, gasIncluded, gasIncluded7702, gasSponsored, }, sentAmount, toTokenAmount, }, requireApproval = false, isDelegatedAccount = false, }) => {
216
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
229
217
  const isGasless = gasIncluded || gasIncluded7702;
230
- const selectedAccount = messenger.call('AccountsController:getAccountByAddress', trade.from);
218
+ const selectedAccount = (0, accounts_1.getAccountByAddress)(messenger, trade.from);
231
219
  if (!selectedAccount) {
232
220
  throw new Error('Failed to submit cross-chain swap batch transaction: unknown account in trade data');
233
221
  }
234
222
  const hexChainId = (0, bridge_controller_1.formatChainIdToHex)(trade.chainId);
235
- const networkClientId = messenger.call('NetworkController:findNetworkClientIdByChainId', hexChainId);
223
+ const networkClientId = (0, network_1.getNetworkClientIdByChainId)(messenger, hexChainId);
236
224
  // Gas fields should be omitted only when gas is sponsored via 7702
237
225
  const skipGasFields = gasIncluded7702 === true;
238
226
  // Enable 7702 batching when the quote includes gasless 7702 support,
239
227
  // or when the account is already delegated (to avoid the in-flight
240
228
  // transaction limit for delegated accounts)
241
- const disable7702 = !skipGasFields && !isDelegatedAccount;
229
+ let disable7702 = !skipGasFields && !isDelegatedAccount;
230
+ // For gasless transactions with STX/sendBundle we keep disabling 7702.
231
+ if (gasIncluded && !gasIncluded7702) {
232
+ disable7702 = true;
233
+ }
242
234
  const transactions = [];
243
235
  if (resetApproval) {
244
- const gasFees = await (0, gas_1.calculateGasFees)(skipGasFields, messenger, estimateGasFeeFn, resetApproval, networkClientId, hexChainId, isGasless ? txFee : undefined);
236
+ const gasFees = await (0, exports.calculateGasFees)(skipGasFields, messenger, resetApproval, networkClientId, hexChainId, isGasless ? txFee : undefined);
245
237
  transactions.push({
246
238
  type: isBridgeTx
247
239
  ? transaction_controller_1.TransactionType.bridgeApproval
@@ -250,7 +242,7 @@ const getAddTransactionBatchParams = async ({ messenger, isBridgeTx, approval, r
250
242
  });
251
243
  }
252
244
  if (approval) {
253
- const gasFees = await (0, gas_1.calculateGasFees)(skipGasFields, messenger, estimateGasFeeFn, approval, networkClientId, hexChainId, isGasless ? txFee : undefined);
245
+ const gasFees = await (0, exports.calculateGasFees)(skipGasFields, messenger, approval, networkClientId, hexChainId, isGasless ? txFee : undefined);
254
246
  transactions.push({
255
247
  type: isBridgeTx
256
248
  ? transaction_controller_1.TransactionType.bridgeApproval
@@ -258,7 +250,7 @@ const getAddTransactionBatchParams = async ({ messenger, isBridgeTx, approval, r
258
250
  params: (0, exports.toBatchTxParams)(skipGasFields, approval, gasFees),
259
251
  });
260
252
  }
261
- const gasFees = await (0, gas_1.calculateGasFees)(skipGasFields, messenger, estimateGasFeeFn, trade, networkClientId, hexChainId, isGasless ? txFee : undefined);
253
+ const gasFees = await (0, exports.calculateGasFees)(skipGasFields, messenger, trade, networkClientId, hexChainId, isGasless ? txFee : undefined);
262
254
  transactions.push({
263
255
  type: isBridgeTx ? transaction_controller_1.TransactionType.bridge : transaction_controller_1.TransactionType.swap,
264
256
  params: (0, exports.toBatchTxParams)(skipGasFields, trade, gasFees),
@@ -280,15 +272,16 @@ const getAddTransactionBatchParams = async ({ messenger, isBridgeTx, approval, r
280
272
  return transactionParams;
281
273
  };
282
274
  exports.getAddTransactionBatchParams = getAddTransactionBatchParams;
283
- const findAndUpdateTransactionsInBatch = ({ messenger, updateTransactionFn, batchId, txDataByType, }) => {
284
- const txs = messenger.call('TransactionController:getState').transactions;
275
+ const findAndUpdateTransactionsInBatch = ({ messenger, batchId, txDataByType, }) => {
276
+ const txs = (0, exports.getTransactions)(messenger);
285
277
  const txBatch = {
286
278
  approvalMeta: undefined,
287
279
  tradeMeta: undefined,
288
280
  };
289
281
  // This is a workaround to update the tx type after the tx is signed
290
282
  // TODO: remove this once the tx type for batch txs is preserved in the tx controller
291
- Object.entries(txDataByType).forEach(([txType, txData]) => {
283
+ const txEntries = Object.entries(txDataByType);
284
+ txEntries.forEach(([txType, txData]) => {
292
285
  // Skip types not present in the batch (e.g. swap entry is undefined for bridge txs)
293
286
  if (txData === undefined) {
294
287
  return;
@@ -323,45 +316,107 @@ const findAndUpdateTransactionsInBatch = ({ messenger, updateTransactionFn, batc
323
316
  });
324
317
  if (txMeta) {
325
318
  const updatedTx = { ...txMeta, type: txType };
326
- updateTransactionFn(updatedTx, `Update tx type to ${txType}`);
327
- txBatch[[transaction_controller_1.TransactionType.bridgeApproval, transaction_controller_1.TransactionType.swapApproval].includes(txType)
328
- ? 'approvalMeta'
329
- : 'tradeMeta'] = updatedTx;
319
+ (0, exports.updateTransaction)(messenger, txMeta, { type: txType }, `Update tx type to ${txType}`);
320
+ const txTypes = [
321
+ transaction_controller_1.TransactionType.bridgeApproval,
322
+ transaction_controller_1.TransactionType.swapApproval,
323
+ ];
324
+ txBatch[txTypes.includes(txType) ? 'approvalMeta' : 'tradeMeta'] =
325
+ updatedTx;
330
326
  }
331
327
  });
332
328
  return txBatch;
333
329
  };
334
330
  exports.findAndUpdateTransactionsInBatch = findAndUpdateTransactionsInBatch;
335
- /**
336
- * Determines the key to use for storing a bridge history item.
337
- * Uses actionId for pre-submission tracking, or bridgeTxMetaId for post-submission.
338
- *
339
- * @param actionId - The action ID used for pre-submission tracking
340
- * @param bridgeTxMetaId - The transaction meta ID from bridgeTxMeta
341
- * @returns The key to use for the history item
342
- * @throws Error if neither actionId nor bridgeTxMetaId is provided
343
- */
344
- function getHistoryKey(actionId, bridgeTxMetaId) {
345
- const historyKey = actionId ?? bridgeTxMetaId;
346
- if (!historyKey) {
347
- throw new Error('Cannot add tx to history: either actionId or bridgeTxMeta.id must be provided');
331
+ const addTransactionBatch = async (messenger, addTransactionBatchFn, ...args) => {
332
+ const txDataByType = {
333
+ [transaction_controller_1.TransactionType.bridgeApproval]: args[0].transactions.find(({ type }) => type === transaction_controller_1.TransactionType.bridgeApproval)?.params.data,
334
+ [transaction_controller_1.TransactionType.swapApproval]: args[0].transactions.find(({ type }) => type === transaction_controller_1.TransactionType.swapApproval)?.params.data,
335
+ [transaction_controller_1.TransactionType.bridge]: args[0].transactions.find(({ type }) => type === transaction_controller_1.TransactionType.bridge)?.params.data,
336
+ [transaction_controller_1.TransactionType.swap]: args[0].transactions.find(({ type }) => type === transaction_controller_1.TransactionType.swap)?.params.data,
337
+ };
338
+ const { batchId } = await addTransactionBatchFn(...args);
339
+ const { approvalMeta, tradeMeta } = (0, exports.findAndUpdateTransactionsInBatch)({
340
+ messenger,
341
+ batchId,
342
+ txDataByType,
343
+ });
344
+ if (!tradeMeta) {
345
+ throw new Error('Failed to update cross-chain swap transaction batch: tradeMeta not found');
348
346
  }
349
- return historyKey;
350
- }
351
- exports.getHistoryKey = getHistoryKey;
347
+ return { approvalMeta, tradeMeta };
348
+ };
349
+ exports.addTransactionBatch = addTransactionBatch;
350
+ // TODO rename
351
+ const getGasFeesForSubmission = async (messenger, transactionParams, networkClientId, chainId, txFee) => {
352
+ const { gas } = transactionParams;
353
+ // If txFee is provided (gasIncluded case), use the quote's gas fees
354
+ // Convert to hex since txFee values from the quote are decimal strings
355
+ if (txFee) {
356
+ return {
357
+ maxFeePerGas: (0, controller_utils_1.toHex)(txFee.maxFeePerGas),
358
+ maxPriorityFeePerGas: (0, controller_utils_1.toHex)(txFee.maxPriorityFeePerGas),
359
+ gas: gas ? (0, controller_utils_1.toHex)(gas) : undefined,
360
+ };
361
+ }
362
+ const { maxFeePerGas, maxPriorityFeePerGas } = await (0, exports.getTxGasEstimates)(messenger, {
363
+ transactionParams,
364
+ chainId,
365
+ networkClientId,
366
+ });
367
+ return {
368
+ maxFeePerGas,
369
+ maxPriorityFeePerGas,
370
+ gas: gas ? (0, controller_utils_1.toHex)(gas) : undefined,
371
+ };
372
+ };
352
373
  /**
353
- * Extracts and validates the intent data from a quote response.
374
+ * Submits an EVM transaction to the TransactionController
354
375
  *
355
- * @param quoteResponse - The quote response that may contain intent data
356
- * @returns The intent data from the quote
357
- * @throws Error if the quote does not contain intent data
376
+ * @param params - The parameters for the transaction
377
+ * @param params.transactionType - The type of transaction to submit
378
+ * @param params.trade - The trade data to confirm
379
+ * @param params.requireApproval - Whether to require approval for the transaction
380
+ * @param params.txFee - Optional gas fee parameters from the quote (used when gasIncluded is true)
381
+ * @param params.txFee.maxFeePerGas - The maximum fee per gas from the quote
382
+ * @param params.txFee.maxPriorityFeePerGas - The maximum priority fee per gas from the quote
383
+ * @param params.actionId - Optional actionId for pre-submission history (if not provided, one is generated)
384
+ * @param params.messenger - The messenger to use for the transaction
385
+ * @returns The transaction meta
358
386
  */
359
- function getIntentFromQuote(quoteResponse) {
360
- const { intent } = quoteResponse.quote;
361
- if (!intent) {
362
- throw new Error('submitIntent: missing intent data');
387
+ const submitEvmTransaction = async ({ messenger, trade, transactionType, requireApproval = false, txFee,
388
+ // Use provided actionId (for pre-submission history) or generate one
389
+ actionId = (0, exports.generateActionId)(), }) => {
390
+ const selectedAccount = (0, accounts_1.getAccountByAddress)(messenger, trade.from);
391
+ if (!selectedAccount) {
392
+ throw new Error('Failed to submit cross-chain swap transaction: unknown account in trade data');
363
393
  }
364
- return intent;
365
- }
366
- exports.getIntentFromQuote = getIntentFromQuote;
394
+ const hexChainId = (0, bridge_controller_1.formatChainIdToHex)(trade.chainId);
395
+ const networkClientId = (0, network_1.getNetworkClientIdByChainId)(messenger, hexChainId);
396
+ const requestOptions = {
397
+ actionId,
398
+ networkClientId,
399
+ requireApproval,
400
+ type: transactionType,
401
+ origin: 'metamask',
402
+ };
403
+ // Exclude gasLimit from trade to avoid type issues (it can be null)
404
+ const { gasLimit: tradeGasLimit, ...tradeWithoutGasLimit } = trade;
405
+ const transactionParams = {
406
+ ...tradeWithoutGasLimit,
407
+ chainId: hexChainId,
408
+ // Only add gasLimit and gas if they're valid (not undefined/null/zero)
409
+ ...(tradeGasLimit &&
410
+ tradeGasLimit !== 0 && {
411
+ gasLimit: tradeGasLimit.toString(),
412
+ gas: tradeGasLimit.toString(),
413
+ }),
414
+ };
415
+ const transactionParamsWithMaxGas = {
416
+ ...transactionParams,
417
+ ...(await getGasFeesForSubmission(messenger, transactionParams, networkClientId, hexChainId, txFee)),
418
+ };
419
+ return await (0, exports.addTransaction)(messenger, transactionParamsWithMaxGas, requestOptions);
420
+ };
421
+ exports.submitEvmTransaction = submitEvmTransaction;
367
422
  //# sourceMappingURL=transaction.cjs.map