@metamask/bridge-status-controller 69.0.0 → 70.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -1
- package/dist/bridge-status-controller.cjs +115 -354
- package/dist/bridge-status-controller.cjs.map +1 -1
- package/dist/bridge-status-controller.d.cts +3 -5
- package/dist/bridge-status-controller.d.cts.map +1 -1
- package/dist/bridge-status-controller.d.mts +3 -5
- package/dist/bridge-status-controller.d.mts.map +1 -1
- package/dist/bridge-status-controller.intent.cjs +12 -25
- package/dist/bridge-status-controller.intent.cjs.map +1 -1
- package/dist/bridge-status-controller.intent.d.cts +3 -14
- package/dist/bridge-status-controller.intent.d.cts.map +1 -1
- package/dist/bridge-status-controller.intent.d.mts +3 -14
- package/dist/bridge-status-controller.intent.d.mts.map +1 -1
- package/dist/bridge-status-controller.intent.mjs +12 -25
- package/dist/bridge-status-controller.intent.mjs.map +1 -1
- package/dist/bridge-status-controller.mjs +118 -357
- package/dist/bridge-status-controller.mjs.map +1 -1
- package/dist/index.cjs +1 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +0 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +0 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +11 -5
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +11 -5
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils/accounts.cjs +8 -0
- package/dist/utils/accounts.cjs.map +1 -0
- package/dist/utils/accounts.d.cts +36 -0
- package/dist/utils/accounts.d.cts.map +1 -0
- package/dist/utils/accounts.d.mts +36 -0
- package/dist/utils/accounts.d.mts.map +1 -0
- package/dist/utils/accounts.mjs +4 -0
- package/dist/utils/accounts.mjs.map +1 -0
- package/dist/utils/authentication.cjs +15 -0
- package/dist/utils/authentication.cjs.map +1 -0
- package/dist/utils/authentication.d.cts +3 -0
- package/dist/utils/authentication.d.cts.map +1 -0
- package/dist/utils/authentication.d.mts +3 -0
- package/dist/utils/authentication.d.mts.map +1 -0
- package/dist/utils/authentication.mjs +11 -0
- package/dist/utils/authentication.mjs.map +1 -0
- package/dist/utils/bridge-status.cjs +17 -1
- package/dist/utils/bridge-status.cjs.map +1 -1
- package/dist/utils/bridge-status.d.cts +8 -2
- package/dist/utils/bridge-status.d.cts.map +1 -1
- package/dist/utils/bridge-status.d.mts +8 -2
- package/dist/utils/bridge-status.d.mts.map +1 -1
- package/dist/utils/bridge-status.mjs +15 -0
- package/dist/utils/bridge-status.mjs.map +1 -1
- package/dist/utils/bridge.cjs +16 -0
- package/dist/utils/bridge.cjs.map +1 -0
- package/dist/utils/bridge.d.cts +10 -0
- package/dist/utils/bridge.d.cts.map +1 -0
- package/dist/utils/bridge.d.mts +10 -0
- package/dist/utils/bridge.d.mts.map +1 -0
- package/dist/utils/bridge.mjs +11 -0
- package/dist/utils/bridge.mjs.map +1 -0
- package/dist/utils/gas.cjs +1 -61
- package/dist/utils/gas.cjs.map +1 -1
- package/dist/utils/gas.d.cts +3 -26
- package/dist/utils/gas.d.cts.map +1 -1
- package/dist/utils/gas.d.mts +3 -26
- package/dist/utils/gas.d.mts.map +1 -1
- package/dist/utils/gas.mjs +0 -58
- package/dist/utils/gas.mjs.map +1 -1
- package/dist/utils/history.cjs +98 -0
- package/dist/utils/history.cjs.map +1 -0
- package/dist/utils/history.d.cts +22 -0
- package/dist/utils/history.d.cts.map +1 -0
- package/dist/utils/history.d.mts +22 -0
- package/dist/utils/history.d.mts.map +1 -0
- package/dist/utils/history.mjs +91 -0
- package/dist/utils/history.mjs.map +1 -0
- package/dist/utils/intent-api.cjs +41 -26
- package/dist/utils/intent-api.cjs.map +1 -1
- package/dist/utils/intent-api.d.cts +16 -3
- package/dist/utils/intent-api.d.cts.map +1 -1
- package/dist/utils/intent-api.d.mts +16 -3
- package/dist/utils/intent-api.d.mts.map +1 -1
- package/dist/utils/intent-api.mjs +38 -25
- package/dist/utils/intent-api.mjs.map +1 -1
- package/dist/utils/keyring.cjs +12 -0
- package/dist/utils/keyring.cjs.map +1 -0
- package/dist/utils/keyring.d.cts +8 -0
- package/dist/utils/keyring.d.cts.map +1 -0
- package/dist/utils/keyring.d.mts +8 -0
- package/dist/utils/keyring.d.mts.map +1 -0
- package/dist/utils/keyring.mjs +8 -0
- package/dist/utils/keyring.mjs.map +1 -0
- package/dist/utils/network.cjs +17 -0
- package/dist/utils/network.cjs.map +1 -0
- package/dist/utils/network.d.cts +5 -0
- package/dist/utils/network.d.cts.map +1 -0
- package/dist/utils/network.d.mts +5 -0
- package/dist/utils/network.d.mts.map +1 -0
- package/dist/utils/network.mjs +12 -0
- package/dist/utils/network.mjs.map +1 -0
- package/dist/utils/snaps.cjs +146 -1
- package/dist/utils/snaps.cjs.map +1 -1
- package/dist/utils/snaps.d.cts +48 -0
- package/dist/utils/snaps.d.cts.map +1 -1
- package/dist/utils/snaps.d.mts +48 -0
- package/dist/utils/snaps.d.mts.map +1 -1
- package/dist/utils/snaps.mjs +141 -0
- package/dist/utils/snaps.mjs.map +1 -1
- package/dist/utils/trace.cjs +31 -0
- package/dist/utils/trace.cjs.map +1 -0
- package/dist/utils/trace.d.cts +17 -0
- package/dist/utils/trace.d.cts.map +1 -0
- package/dist/utils/trace.d.mts +17 -0
- package/dist/utils/trace.d.mts.map +1 -0
- package/dist/utils/trace.mjs +26 -0
- package/dist/utils/trace.mjs.map +1 -0
- package/dist/utils/transaction.cjs +239 -184
- package/dist/utils/transaction.cjs.map +1 -1
- package/dist/utils/transaction.d.cts +85 -236
- package/dist/utils/transaction.d.cts.map +1 -1
- package/dist/utils/transaction.d.mts +85 -236
- package/dist/utils/transaction.d.mts.map +1 -1
- package/dist/utils/transaction.mjs +226 -176
- package/dist/utils/transaction.mjs.map +1 -1
- package/dist/utils/validators.d.cts +2 -2
- package/dist/utils/validators.d.mts +2 -2
- package/package.json +3 -3
|
@@ -1,115 +1,129 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
2
|
+
import { ChainId, formatChainIdToHex, BRIDGE_PREFERRED_GAS_ESTIMATE } from "@metamask/bridge-controller";
|
|
2
3
|
import { toHex } from "@metamask/controller-utils";
|
|
3
4
|
import { TransactionStatus, TransactionType } from "@metamask/transaction-controller";
|
|
4
5
|
import { createProjectLogger } from "@metamask/utils";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { BigNumber } from "bignumber.js";
|
|
7
|
+
import { getAccountByAddress } from "./accounts.mjs";
|
|
8
|
+
import { getNetworkClientIdByChainId } from "./network.mjs";
|
|
8
9
|
import { APPROVAL_DELAY_MS } from "../constants.mjs";
|
|
9
|
-
export const
|
|
10
|
-
|
|
10
|
+
export const getGasFeeEstimates = async (messenger, args) => {
|
|
11
|
+
const { estimates } = await messenger.call('TransactionController:estimateGasFee', args);
|
|
12
|
+
if (BRIDGE_PREFERRED_GAS_ESTIMATE in estimates &&
|
|
13
|
+
typeof estimates[BRIDGE_PREFERRED_GAS_ESTIMATE] === 'object' &&
|
|
14
|
+
'maxFeePerGas' in estimates[BRIDGE_PREFERRED_GAS_ESTIMATE] &&
|
|
15
|
+
'maxPriorityFeePerGas' in estimates[BRIDGE_PREFERRED_GAS_ESTIMATE]) {
|
|
16
|
+
return estimates[BRIDGE_PREFERRED_GAS_ESTIMATE];
|
|
17
|
+
}
|
|
18
|
+
return {};
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Get the gas fee estimates for a transaction
|
|
22
|
+
*
|
|
23
|
+
* @param messenger - The messenger for the gas fee estimates
|
|
24
|
+
* @param estimateGasFeeParams - The parameters for the {@link TransactionController.estimateGasFee} method
|
|
25
|
+
|
|
26
|
+
* @returns The gas fee estimates for the transaction
|
|
27
|
+
*/
|
|
28
|
+
export const getTxGasEstimates = async (messenger, estimateGasFeeParams) => {
|
|
29
|
+
const { gasFeeEstimates } = messenger.call('GasFeeController:getState');
|
|
30
|
+
const estimatedBaseFee = 'estimatedBaseFee' in gasFeeEstimates
|
|
31
|
+
? gasFeeEstimates.estimatedBaseFee
|
|
32
|
+
: '0';
|
|
33
|
+
// Get transaction's 1559 gas fee estimates
|
|
34
|
+
const { maxFeePerGas, maxPriorityFeePerGas } = await getGasFeeEstimates(messenger, estimateGasFeeParams);
|
|
35
|
+
/**
|
|
36
|
+
* @deprecated this is unused
|
|
37
|
+
*/
|
|
38
|
+
const baseAndPriorityFeePerGas = maxPriorityFeePerGas
|
|
39
|
+
? new BigNumber(estimatedBaseFee, 10)
|
|
40
|
+
.times(10 ** 9)
|
|
41
|
+
.plus(maxPriorityFeePerGas, 16)
|
|
42
|
+
: undefined;
|
|
11
43
|
return {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
destChainId: quoteResponse.quote.destChainId,
|
|
16
|
-
quote: quoteResponse.quote,
|
|
17
|
-
refuel: Boolean(quoteResponse.quote.refuel),
|
|
44
|
+
baseAndPriorityFeePerGas,
|
|
45
|
+
maxFeePerGas,
|
|
46
|
+
maxPriorityFeePerGas,
|
|
18
47
|
};
|
|
19
48
|
};
|
|
20
|
-
export const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
destinationChainId = formatChainIdToHex(quoteResponse.quote.destChainId);
|
|
49
|
+
export const calculateGasFees = async (skipGasFields, messenger, { chainId: _, gasLimit, ...trade }, networkClientId, chainId, txFee) => {
|
|
50
|
+
if (skipGasFields) {
|
|
51
|
+
return {};
|
|
25
52
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
destinationChainId = '0x1'; // Default to mainnet
|
|
53
|
+
if (txFee) {
|
|
54
|
+
return { ...txFee, gas: gasLimit?.toString() };
|
|
29
55
|
}
|
|
56
|
+
const transactionParams = {
|
|
57
|
+
...trade,
|
|
58
|
+
gas: gasLimit?.toString(),
|
|
59
|
+
data: trade.data,
|
|
60
|
+
to: trade.to,
|
|
61
|
+
value: trade.value,
|
|
62
|
+
};
|
|
63
|
+
const { maxFeePerGas, maxPriorityFeePerGas } = await getTxGasEstimates(messenger, {
|
|
64
|
+
transactionParams,
|
|
65
|
+
networkClientId,
|
|
66
|
+
chainId,
|
|
67
|
+
});
|
|
68
|
+
const maxGasLimit = toHex(transactionParams.gas ?? 0);
|
|
30
69
|
return {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
sourceTokenDecimals: quoteResponse.quote.srcAsset.decimals,
|
|
35
|
-
sourceTokenAddress: quoteResponse.quote.srcAsset.address,
|
|
36
|
-
destinationTokenAmount: quoteResponse.quote.destTokenAmount,
|
|
37
|
-
destinationTokenSymbol: quoteResponse.quote.destAsset.symbol,
|
|
38
|
-
destinationTokenDecimals: quoteResponse.quote.destAsset.decimals,
|
|
39
|
-
destinationTokenAddress: quoteResponse.quote.destAsset.address,
|
|
40
|
-
// chainId is now excluded from this function and handled by the caller
|
|
41
|
-
approvalTxId,
|
|
42
|
-
// this is the decimal (non atomic) amount (not USD value) of source token to swap
|
|
43
|
-
swapTokenValue: quoteResponse.sentAmount.amount,
|
|
70
|
+
maxFeePerGas,
|
|
71
|
+
maxPriorityFeePerGas,
|
|
72
|
+
gas: maxGasLimit,
|
|
44
73
|
};
|
|
45
74
|
};
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
let hash;
|
|
60
|
-
// Handle different response formats
|
|
61
|
-
if (typeof snapResponse === 'string') {
|
|
62
|
-
hash = snapResponse;
|
|
63
|
-
}
|
|
64
|
-
else if (snapResponse && typeof snapResponse === 'object') {
|
|
65
|
-
// Check for new unified interface response format first
|
|
66
|
-
if ('transactionId' in snapResponse && snapResponse.transactionId) {
|
|
67
|
-
hash = snapResponse.transactionId;
|
|
68
|
-
}
|
|
69
|
-
else if ('result' in snapResponse &&
|
|
70
|
-
snapResponse.result &&
|
|
71
|
-
typeof snapResponse.result === 'object') {
|
|
72
|
-
// Try to extract signature from common locations in response object
|
|
73
|
-
hash =
|
|
74
|
-
snapResponse.result.signature ||
|
|
75
|
-
snapResponse.result.txid ||
|
|
76
|
-
snapResponse.result.hash ||
|
|
77
|
-
snapResponse.result.txHash;
|
|
78
|
-
}
|
|
79
|
-
else if ('signature' in snapResponse &&
|
|
80
|
-
snapResponse.signature &&
|
|
81
|
-
typeof snapResponse.signature === 'string') {
|
|
82
|
-
hash = snapResponse.signature;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
const isBridgeTx = isCrossChain(quoteResponse.quote.srcChainId, quoteResponse.quote.destChainId);
|
|
86
|
-
let hexChainId;
|
|
75
|
+
export const getTransactions = (messenger) => {
|
|
76
|
+
return messenger.call('TransactionController:getState').transactions ?? [];
|
|
77
|
+
};
|
|
78
|
+
export const getTransactionMetaById = (messenger, txId) => {
|
|
79
|
+
return getTransactions(messenger).find((tx) => tx.id === txId);
|
|
80
|
+
};
|
|
81
|
+
export const getTransactionMetaByHash = (messenger, txHash) => {
|
|
82
|
+
return getTransactions(messenger).find((tx) => tx.hash === txHash);
|
|
83
|
+
};
|
|
84
|
+
export const updateTransaction = (messenger, txMeta, txMetaUpdates, note) => {
|
|
85
|
+
return messenger.call('TransactionController:updateTransaction', { ...txMeta, ...txMetaUpdates }, note);
|
|
86
|
+
};
|
|
87
|
+
export const checkIsDelegatedAccount = async (messenger, fromAddress, chainIds) => {
|
|
87
88
|
try {
|
|
88
|
-
|
|
89
|
+
const atomicBatchSupport = await messenger.call('TransactionController:isAtomicBatchSupported', {
|
|
90
|
+
address: fromAddress,
|
|
91
|
+
chainIds,
|
|
92
|
+
});
|
|
93
|
+
return atomicBatchSupport.some((entry) => entry.isSupported && entry.delegationAddress);
|
|
89
94
|
}
|
|
90
95
|
catch {
|
|
91
|
-
|
|
92
|
-
// Fallback to Ethereum mainnet for now
|
|
93
|
-
hexChainId = '0x1';
|
|
96
|
+
return false;
|
|
94
97
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
98
|
+
};
|
|
99
|
+
const waitForHashAndReturnFinalTxMeta = async (messenger, hashPromise) => {
|
|
100
|
+
const txHash = await hashPromise;
|
|
101
|
+
const finalTransactionMeta = getTransactionMetaByHash(messenger, txHash);
|
|
102
|
+
if (!finalTransactionMeta) {
|
|
103
|
+
throw new Error('Failed to submit cross-chain swap tx: txMeta for txHash was not found');
|
|
104
|
+
}
|
|
105
|
+
return finalTransactionMeta;
|
|
106
|
+
};
|
|
107
|
+
export const addTransaction = async (messenger, ...args) => {
|
|
108
|
+
const { result } = await messenger.call('TransactionController:addTransaction', ...args);
|
|
109
|
+
return await waitForHashAndReturnFinalTxMeta(messenger, result);
|
|
110
|
+
};
|
|
111
|
+
export const generateActionId = () => (Date.now() + Math.random()).toString();
|
|
112
|
+
/**
|
|
113
|
+
* Adds a synthetic transaction to the TransactionController to display pending intent orders in the UI
|
|
114
|
+
*
|
|
115
|
+
* @param messenger - The messenger to use for the transaction
|
|
116
|
+
* @param args - The arguments for the transaction
|
|
117
|
+
* @returns The transaction meta
|
|
118
|
+
*/
|
|
119
|
+
export const addSyntheticTransaction = async (messenger, ...args) => {
|
|
120
|
+
const { transactionMeta } = await messenger.call('TransactionController:addTransaction', args[0], {
|
|
121
|
+
origin: 'metamask',
|
|
122
|
+
actionId: generateActionId(),
|
|
123
|
+
isStateOnly: true,
|
|
124
|
+
...args[1],
|
|
125
|
+
});
|
|
126
|
+
return transactionMeta;
|
|
113
127
|
};
|
|
114
128
|
export const handleApprovalDelay = async (srcChainId) => {
|
|
115
129
|
if ([ChainId.LINEA, ChainId.BASE].includes(srcChainId)) {
|
|
@@ -133,32 +147,20 @@ export const handleMobileHardwareWalletDelay = async (requireApproval) => {
|
|
|
133
147
|
}
|
|
134
148
|
};
|
|
135
149
|
/**
|
|
136
|
-
*
|
|
137
|
-
* Uses the new unified ClientRequest:signAndSendTransaction interface
|
|
150
|
+
* Waits until a given transaction (by id) reaches confirmed/finalized status or fails/times out.
|
|
138
151
|
*
|
|
139
|
-
* @
|
|
140
|
-
* @param
|
|
141
|
-
* @param
|
|
142
|
-
* @
|
|
152
|
+
* @deprecated use addTransaction util
|
|
153
|
+
* @param messenger - the BridgeStatusControllerMessenger
|
|
154
|
+
* @param txId - the transaction ID
|
|
155
|
+
* @param options - the options for the timeout and poll
|
|
156
|
+
* @param options.timeoutMs - the timeout in milliseconds
|
|
157
|
+
* @param options.pollMs - the poll interval in milliseconds
|
|
158
|
+
* @returns the transaction meta
|
|
143
159
|
*/
|
|
144
|
-
export const getClientRequest = (trade, srcChainId, selectedAccount) => {
|
|
145
|
-
const scope = formatChainIdToCaip(srcChainId);
|
|
146
|
-
const transactionData = extractTradeData(trade);
|
|
147
|
-
// Tron trades need the visible flag and contract type to be included in the request options
|
|
148
|
-
const options = isTronTrade(trade)
|
|
149
|
-
? {
|
|
150
|
-
visible: trade.visible,
|
|
151
|
-
type: trade.raw_data?.contract?.[0]?.type,
|
|
152
|
-
}
|
|
153
|
-
: undefined;
|
|
154
|
-
// Use the new unified interface
|
|
155
|
-
return createClientTransactionRequest(selectedAccount.metadata.snap?.id, transactionData, scope, selectedAccount.id, options);
|
|
156
|
-
};
|
|
157
160
|
export const waitForTxConfirmation = async (messenger, txId, { timeoutMs = 5 * 60000, pollMs = 3000, } = {}) => {
|
|
158
161
|
const start = Date.now();
|
|
159
162
|
while (true) {
|
|
160
|
-
const
|
|
161
|
-
const meta = transactions.find((tx) => tx.id === txId);
|
|
163
|
+
const meta = getTransactionMetaById(messenger, txId);
|
|
162
164
|
if (meta) {
|
|
163
165
|
if (meta.status === TransactionStatus.confirmed) {
|
|
164
166
|
return meta;
|
|
@@ -175,26 +177,6 @@ export const waitForTxConfirmation = async (messenger, txId, { timeoutMs = 5 * 6
|
|
|
175
177
|
await new Promise((resolve) => setTimeout(resolve, pollMs));
|
|
176
178
|
}
|
|
177
179
|
};
|
|
178
|
-
export const rekeyHistoryItemInState = (state, actionId, txMeta) => {
|
|
179
|
-
const historyItem = state.txHistory[actionId];
|
|
180
|
-
if (!historyItem) {
|
|
181
|
-
return false;
|
|
182
|
-
}
|
|
183
|
-
state.txHistory[txMeta.id] = {
|
|
184
|
-
...historyItem,
|
|
185
|
-
txMetaId: txMeta.id,
|
|
186
|
-
originalTransactionId: historyItem.originalTransactionId ?? txMeta.id,
|
|
187
|
-
status: {
|
|
188
|
-
...historyItem.status,
|
|
189
|
-
srcChain: {
|
|
190
|
-
...historyItem.status.srcChain,
|
|
191
|
-
txHash: txMeta.hash ?? historyItem.status.srcChain?.txHash,
|
|
192
|
-
},
|
|
193
|
-
},
|
|
194
|
-
};
|
|
195
|
-
delete state.txHistory[actionId];
|
|
196
|
-
return true;
|
|
197
|
-
};
|
|
198
180
|
export const toBatchTxParams = (skipGasFields, { chainId, gasLimit, ...trade }, { maxFeePerGas, maxPriorityFeePerGas, gas, }) => {
|
|
199
181
|
const params = {
|
|
200
182
|
...trade,
|
|
@@ -212,23 +194,28 @@ export const toBatchTxParams = (skipGasFields, { chainId, gasLimit, ...trade },
|
|
|
212
194
|
maxPriorityFeePerGas: toHex(maxPriorityFeePerGas ?? 0),
|
|
213
195
|
};
|
|
214
196
|
};
|
|
215
|
-
export const getAddTransactionBatchParams = async ({ messenger, isBridgeTx, approval, resetApproval, trade, quoteResponse: { quote: { feeData: { txFee }, gasIncluded, gasIncluded7702, gasSponsored, }, sentAmount, toTokenAmount, }, requireApproval = false, isDelegatedAccount = false,
|
|
197
|
+
export const getAddTransactionBatchParams = async ({ messenger, isBridgeTx, approval, resetApproval, trade, quoteResponse: { quote: { feeData: { txFee }, gasIncluded, gasIncluded7702, gasSponsored, }, sentAmount, toTokenAmount, }, requireApproval = false, isDelegatedAccount = false, }) => {
|
|
198
|
+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
|
216
199
|
const isGasless = gasIncluded || gasIncluded7702;
|
|
217
|
-
const selectedAccount = messenger
|
|
200
|
+
const selectedAccount = getAccountByAddress(messenger, trade.from);
|
|
218
201
|
if (!selectedAccount) {
|
|
219
202
|
throw new Error('Failed to submit cross-chain swap batch transaction: unknown account in trade data');
|
|
220
203
|
}
|
|
221
204
|
const hexChainId = formatChainIdToHex(trade.chainId);
|
|
222
|
-
const networkClientId = messenger
|
|
205
|
+
const networkClientId = getNetworkClientIdByChainId(messenger, hexChainId);
|
|
223
206
|
// Gas fields should be omitted only when gas is sponsored via 7702
|
|
224
207
|
const skipGasFields = gasIncluded7702 === true;
|
|
225
208
|
// Enable 7702 batching when the quote includes gasless 7702 support,
|
|
226
209
|
// or when the account is already delegated (to avoid the in-flight
|
|
227
210
|
// transaction limit for delegated accounts)
|
|
228
|
-
|
|
211
|
+
let disable7702 = !skipGasFields && !isDelegatedAccount;
|
|
212
|
+
// For gasless transactions with STX/sendBundle we keep disabling 7702.
|
|
213
|
+
if (gasIncluded && !gasIncluded7702) {
|
|
214
|
+
disable7702 = true;
|
|
215
|
+
}
|
|
229
216
|
const transactions = [];
|
|
230
217
|
if (resetApproval) {
|
|
231
|
-
const gasFees = await calculateGasFees(skipGasFields, messenger,
|
|
218
|
+
const gasFees = await calculateGasFees(skipGasFields, messenger, resetApproval, networkClientId, hexChainId, isGasless ? txFee : undefined);
|
|
232
219
|
transactions.push({
|
|
233
220
|
type: isBridgeTx
|
|
234
221
|
? TransactionType.bridgeApproval
|
|
@@ -237,7 +224,7 @@ export const getAddTransactionBatchParams = async ({ messenger, isBridgeTx, appr
|
|
|
237
224
|
});
|
|
238
225
|
}
|
|
239
226
|
if (approval) {
|
|
240
|
-
const gasFees = await calculateGasFees(skipGasFields, messenger,
|
|
227
|
+
const gasFees = await calculateGasFees(skipGasFields, messenger, approval, networkClientId, hexChainId, isGasless ? txFee : undefined);
|
|
241
228
|
transactions.push({
|
|
242
229
|
type: isBridgeTx
|
|
243
230
|
? TransactionType.bridgeApproval
|
|
@@ -245,7 +232,7 @@ export const getAddTransactionBatchParams = async ({ messenger, isBridgeTx, appr
|
|
|
245
232
|
params: toBatchTxParams(skipGasFields, approval, gasFees),
|
|
246
233
|
});
|
|
247
234
|
}
|
|
248
|
-
const gasFees = await calculateGasFees(skipGasFields, messenger,
|
|
235
|
+
const gasFees = await calculateGasFees(skipGasFields, messenger, trade, networkClientId, hexChainId, isGasless ? txFee : undefined);
|
|
249
236
|
transactions.push({
|
|
250
237
|
type: isBridgeTx ? TransactionType.bridge : TransactionType.swap,
|
|
251
238
|
params: toBatchTxParams(skipGasFields, trade, gasFees),
|
|
@@ -266,15 +253,16 @@ export const getAddTransactionBatchParams = async ({ messenger, isBridgeTx, appr
|
|
|
266
253
|
};
|
|
267
254
|
return transactionParams;
|
|
268
255
|
};
|
|
269
|
-
export const findAndUpdateTransactionsInBatch = ({ messenger,
|
|
270
|
-
const txs = messenger
|
|
256
|
+
export const findAndUpdateTransactionsInBatch = ({ messenger, batchId, txDataByType, }) => {
|
|
257
|
+
const txs = getTransactions(messenger);
|
|
271
258
|
const txBatch = {
|
|
272
259
|
approvalMeta: undefined,
|
|
273
260
|
tradeMeta: undefined,
|
|
274
261
|
};
|
|
275
262
|
// This is a workaround to update the tx type after the tx is signed
|
|
276
263
|
// TODO: remove this once the tx type for batch txs is preserved in the tx controller
|
|
277
|
-
Object.entries(txDataByType)
|
|
264
|
+
const txEntries = Object.entries(txDataByType);
|
|
265
|
+
txEntries.forEach(([txType, txData]) => {
|
|
278
266
|
// Skip types not present in the batch (e.g. swap entry is undefined for bridge txs)
|
|
279
267
|
if (txData === undefined) {
|
|
280
268
|
return;
|
|
@@ -309,42 +297,104 @@ export const findAndUpdateTransactionsInBatch = ({ messenger, updateTransactionF
|
|
|
309
297
|
});
|
|
310
298
|
if (txMeta) {
|
|
311
299
|
const updatedTx = { ...txMeta, type: txType };
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
300
|
+
updateTransaction(messenger, txMeta, { type: txType }, `Update tx type to ${txType}`);
|
|
301
|
+
const txTypes = [
|
|
302
|
+
TransactionType.bridgeApproval,
|
|
303
|
+
TransactionType.swapApproval,
|
|
304
|
+
];
|
|
305
|
+
txBatch[txTypes.includes(txType) ? 'approvalMeta' : 'tradeMeta'] =
|
|
306
|
+
updatedTx;
|
|
316
307
|
}
|
|
317
308
|
});
|
|
318
309
|
return txBatch;
|
|
319
310
|
};
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
311
|
+
export const addTransactionBatch = async (messenger, addTransactionBatchFn, ...args) => {
|
|
312
|
+
const txDataByType = {
|
|
313
|
+
[TransactionType.bridgeApproval]: args[0].transactions.find(({ type }) => type === TransactionType.bridgeApproval)?.params.data,
|
|
314
|
+
[TransactionType.swapApproval]: args[0].transactions.find(({ type }) => type === TransactionType.swapApproval)?.params.data,
|
|
315
|
+
[TransactionType.bridge]: args[0].transactions.find(({ type }) => type === TransactionType.bridge)?.params.data,
|
|
316
|
+
[TransactionType.swap]: args[0].transactions.find(({ type }) => type === TransactionType.swap)?.params.data,
|
|
317
|
+
};
|
|
318
|
+
const { batchId } = await addTransactionBatchFn(...args);
|
|
319
|
+
const { approvalMeta, tradeMeta } = findAndUpdateTransactionsInBatch({
|
|
320
|
+
messenger,
|
|
321
|
+
batchId,
|
|
322
|
+
txDataByType,
|
|
323
|
+
});
|
|
324
|
+
if (!tradeMeta) {
|
|
325
|
+
throw new Error('Failed to update cross-chain swap transaction batch: tradeMeta not found');
|
|
326
|
+
}
|
|
327
|
+
return { approvalMeta, tradeMeta };
|
|
328
|
+
};
|
|
329
|
+
// TODO rename
|
|
330
|
+
const getGasFeesForSubmission = async (messenger, transactionParams, networkClientId, chainId, txFee) => {
|
|
331
|
+
const { gas } = transactionParams;
|
|
332
|
+
// If txFee is provided (gasIncluded case), use the quote's gas fees
|
|
333
|
+
// Convert to hex since txFee values from the quote are decimal strings
|
|
334
|
+
if (txFee) {
|
|
335
|
+
return {
|
|
336
|
+
maxFeePerGas: toHex(txFee.maxFeePerGas),
|
|
337
|
+
maxPriorityFeePerGas: toHex(txFee.maxPriorityFeePerGas),
|
|
338
|
+
gas: gas ? toHex(gas) : undefined,
|
|
339
|
+
};
|
|
333
340
|
}
|
|
334
|
-
|
|
335
|
-
|
|
341
|
+
const { maxFeePerGas, maxPriorityFeePerGas } = await getTxGasEstimates(messenger, {
|
|
342
|
+
transactionParams,
|
|
343
|
+
chainId,
|
|
344
|
+
networkClientId,
|
|
345
|
+
});
|
|
346
|
+
return {
|
|
347
|
+
maxFeePerGas,
|
|
348
|
+
maxPriorityFeePerGas,
|
|
349
|
+
gas: gas ? toHex(gas) : undefined,
|
|
350
|
+
};
|
|
351
|
+
};
|
|
336
352
|
/**
|
|
337
|
-
*
|
|
353
|
+
* Submits an EVM transaction to the TransactionController
|
|
338
354
|
*
|
|
339
|
-
* @param
|
|
340
|
-
* @
|
|
341
|
-
* @
|
|
355
|
+
* @param params - The parameters for the transaction
|
|
356
|
+
* @param params.transactionType - The type of transaction to submit
|
|
357
|
+
* @param params.trade - The trade data to confirm
|
|
358
|
+
* @param params.requireApproval - Whether to require approval for the transaction
|
|
359
|
+
* @param params.txFee - Optional gas fee parameters from the quote (used when gasIncluded is true)
|
|
360
|
+
* @param params.txFee.maxFeePerGas - The maximum fee per gas from the quote
|
|
361
|
+
* @param params.txFee.maxPriorityFeePerGas - The maximum priority fee per gas from the quote
|
|
362
|
+
* @param params.actionId - Optional actionId for pre-submission history (if not provided, one is generated)
|
|
363
|
+
* @param params.messenger - The messenger to use for the transaction
|
|
364
|
+
* @returns The transaction meta
|
|
342
365
|
*/
|
|
343
|
-
export
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
366
|
+
export const submitEvmTransaction = async ({ messenger, trade, transactionType, requireApproval = false, txFee,
|
|
367
|
+
// Use provided actionId (for pre-submission history) or generate one
|
|
368
|
+
actionId = generateActionId(), }) => {
|
|
369
|
+
const selectedAccount = getAccountByAddress(messenger, trade.from);
|
|
370
|
+
if (!selectedAccount) {
|
|
371
|
+
throw new Error('Failed to submit cross-chain swap transaction: unknown account in trade data');
|
|
347
372
|
}
|
|
348
|
-
|
|
349
|
-
|
|
373
|
+
const hexChainId = formatChainIdToHex(trade.chainId);
|
|
374
|
+
const networkClientId = getNetworkClientIdByChainId(messenger, hexChainId);
|
|
375
|
+
const requestOptions = {
|
|
376
|
+
actionId,
|
|
377
|
+
networkClientId,
|
|
378
|
+
requireApproval,
|
|
379
|
+
type: transactionType,
|
|
380
|
+
origin: 'metamask',
|
|
381
|
+
};
|
|
382
|
+
// Exclude gasLimit from trade to avoid type issues (it can be null)
|
|
383
|
+
const { gasLimit: tradeGasLimit, ...tradeWithoutGasLimit } = trade;
|
|
384
|
+
const transactionParams = {
|
|
385
|
+
...tradeWithoutGasLimit,
|
|
386
|
+
chainId: hexChainId,
|
|
387
|
+
// Only add gasLimit and gas if they're valid (not undefined/null/zero)
|
|
388
|
+
...(tradeGasLimit &&
|
|
389
|
+
tradeGasLimit !== 0 && {
|
|
390
|
+
gasLimit: tradeGasLimit.toString(),
|
|
391
|
+
gas: tradeGasLimit.toString(),
|
|
392
|
+
}),
|
|
393
|
+
};
|
|
394
|
+
const transactionParamsWithMaxGas = {
|
|
395
|
+
...transactionParams,
|
|
396
|
+
...(await getGasFeesForSubmission(messenger, transactionParams, networkClientId, hexChainId, txFee)),
|
|
397
|
+
};
|
|
398
|
+
return await addTransaction(messenger, transactionParamsWithMaxGas, requestOptions);
|
|
399
|
+
};
|
|
350
400
|
//# sourceMappingURL=transaction.mjs.map
|