@metamask-previews/bridge-status-controller 76.4.0-preview-686aaf7 → 76.4.0-preview-51ecba2

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 (35) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/bridge-status-controller.d.ts.map +1 -1
  3. package/dist/bridge-status-controller.js +78 -40
  4. package/dist/bridge-status-controller.js.map +1 -1
  5. package/dist/strategy/batch-sell-strategy.d.ts.map +1 -1
  6. package/dist/strategy/batch-sell-strategy.js +62 -34
  7. package/dist/strategy/batch-sell-strategy.js.map +1 -1
  8. package/dist/strategy/batch-strategy.d.ts.map +1 -1
  9. package/dist/strategy/batch-strategy.js +38 -13
  10. package/dist/strategy/batch-strategy.js.map +1 -1
  11. package/dist/strategy/evm-strategy.d.ts +2 -28
  12. package/dist/strategy/evm-strategy.d.ts.map +1 -1
  13. package/dist/strategy/evm-strategy.js +62 -39
  14. package/dist/strategy/evm-strategy.js.map +1 -1
  15. package/dist/strategy/intent-strategy.d.ts.map +1 -1
  16. package/dist/strategy/intent-strategy.js +2 -1
  17. package/dist/strategy/intent-strategy.js.map +1 -1
  18. package/dist/strategy/types.d.ts +3 -2
  19. package/dist/strategy/types.d.ts.map +1 -1
  20. package/dist/strategy/types.js.map +1 -1
  21. package/dist/types.d.ts +1 -2
  22. package/dist/types.d.ts.map +1 -1
  23. package/dist/types.js.map +1 -1
  24. package/dist/utils/history.d.ts +2 -2
  25. package/dist/utils/history.d.ts.map +1 -1
  26. package/dist/utils/history.js +64 -25
  27. package/dist/utils/history.js.map +1 -1
  28. package/dist/utils/metrics.d.ts +2 -33
  29. package/dist/utils/metrics.d.ts.map +1 -1
  30. package/dist/utils/metrics.js.map +1 -1
  31. package/dist/utils/transaction.d.ts +2 -0
  32. package/dist/utils/transaction.d.ts.map +1 -1
  33. package/dist/utils/transaction.js +16 -4
  34. package/dist/utils/transaction.js.map +1 -1
  35. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { TransactionType, } from '@metamask/transaction-controller';
1
+ import { generateBatchId, TransactionType, } from '@metamask/transaction-controller';
2
2
  import { findAllTransactionsInBatch, getAddTransactionBatchParams, hasNestedSwapTransactions, is7702Tx, isTradeTx, shouldDisable7702, toQuoteAndTxMetadataBatch, } from '../utils/transaction.js';
3
3
  import { SubmitStep } from './types.js';
4
4
  const getHistoryKeyForQuote = ({ quoteResponse: { quoteId, quote }, }) => quoteId ?? quote.requestId;
@@ -16,6 +16,19 @@ export async function* submitBatchSellHandler(args) {
16
16
  });
17
17
  const { gasIncluded7702, gasIncluded, gasSponsored } = batchSellTrades;
18
18
  const gasFeeToken = tradeData.find(({ type }) => type === TransactionType.tokenMethodTransfer)?.tx.to;
19
+ const batchId = batchIdParam ?? generateBatchId();
20
+ // Create 1 history item for the parent tx or first quote, keyed by the batchId
21
+ yield {
22
+ type: SubmitStep.AddHistoryItem,
23
+ payload: {
24
+ historyKey: batchId,
25
+ quoteResponse: tradeData[0].quoteResponse,
26
+ batchSellData: batchSellTrades,
27
+ bridgeTxMeta: {
28
+ batchId,
29
+ },
30
+ },
31
+ };
19
32
  const transactionParams = await getAddTransactionBatchParams({
20
33
  messenger,
21
34
  tradeData,
@@ -26,14 +39,27 @@ export async function* submitBatchSellHandler(args) {
26
39
  disable7702: shouldDisable7702(gasIncluded7702, gasIncluded, isDelegatedAccount),
27
40
  isGasFeeSponsored: gasSponsored,
28
41
  isGasFeeIncluded: Boolean(gasIncluded7702),
29
- batchId: batchIdParam,
42
+ batchId,
30
43
  skipInitialGasEstimate: gasIncluded7702
31
44
  ? isDelegatedAccount
32
45
  : Boolean(gasFeeToken),
33
46
  excludeNativeTokenForFee: !gasFeeToken,
34
47
  });
35
48
  // Submit the batch to the TransactionController
36
- const { batchId } = await addTransactionBatchFn(transactionParams);
49
+ try {
50
+ await addTransactionBatchFn(transactionParams);
51
+ }
52
+ catch (error) {
53
+ const allTradesInBatch = findAllTransactionsInBatch({
54
+ messenger,
55
+ batchId,
56
+ tradeData,
57
+ });
58
+ // Propagate the error if tx has not been added to the TransactionController
59
+ if (!allTradesInBatch.some(({ txMeta }) => txMeta)) {
60
+ throw error;
61
+ }
62
+ }
37
63
  // Find all batch transaction metas and add them to history
38
64
  const allTradesInBatch = findAllTransactionsInBatch({
39
65
  messenger,
@@ -61,46 +87,48 @@ export async function* submitBatchSellHandler(args) {
61
87
  // `is7702Tx` only means the account is delegated (true even for many-tx
62
88
  // batches), so count the unique txs instead.
63
89
  const isSingleBatchTx = new Set(allTradesInBatch.map(({ txMeta }) => txMeta.id)).size === 1;
64
- // Nested/7702 batch
65
- if (isSingleBatchTx &&
66
- (is7702Tx(firstTradeMeta) || hasNestedSwapTransactions(firstTradeMeta))) {
67
- const quoteIds = Array.from(new Set(allTradesInBatch.map(getHistoryKeyForQuote)));
68
- // Create 1 history item for the parent tx, keyed by the txMeta.id
69
- yield {
70
- type: SubmitStep.AddHistoryItem,
71
- payload: {
72
- historyKey: firstTradeMeta.id,
73
- quoteResponse: firstTradeWithMetadata.quoteResponse,
74
- batchSellData: batchSellTrades,
75
- quoteIds,
76
- bridgeTxMeta: firstTradeMeta,
77
- },
78
- };
79
- // Then create a new history item for each nested trade, keyed by quoteId/requestId
80
- for (const tradeWithMetadata of allTradesInBatch) {
81
- const { quoteResponse } = tradeWithMetadata;
90
+ const isNested7702BatchTx = isSingleBatchTx &&
91
+ (is7702Tx(firstTradeMeta) || hasNestedSwapTransactions(firstTradeMeta));
92
+ // Each trade has its own txMeta if not submitted via 7702
93
+ // Create a new history item for each one, keyed by txMeta.id
94
+ // Note that the approvalTxId is not tracked in history
95
+ for (const [index, tradeWithMetadata] of allTradesInBatch.entries()) {
96
+ // Rekey the initial trade
97
+ if (index === 0) {
98
+ const quoteIds = isNested7702BatchTx
99
+ ? Array.from(new Set(allTradesInBatch.map(getHistoryKeyForQuote)))
100
+ : undefined;
101
+ const initialTrade = isNested7702BatchTx
102
+ ? firstTradeWithMetadata
103
+ : tradeWithMetadata;
82
104
  yield {
83
- type: SubmitStep.AddHistoryItem,
105
+ type: SubmitStep.RekeyHistoryItem,
84
106
  payload: {
85
- historyKey: getHistoryKeyForQuote(tradeWithMetadata),
86
- quoteResponse,
87
- batchSellData: batchSellTrades,
107
+ oldHistoryKey: batchId,
108
+ newHistoryKey: initialTrade.txMeta.id,
109
+ historyItemOverrides: {
110
+ quote: initialTrade.quoteResponse.quote,
111
+ quoteIds,
112
+ },
113
+ tradeMeta: initialTrade.txMeta,
88
114
  },
89
115
  };
90
116
  }
91
- }
92
- else {
93
- // Each trade has its own txMeta if not submitted via 7702
94
- // Create a new history item for each one, keyed by txMeta.id
95
- // Note that the approvalTxId is not tracked in history
96
- for (const { txMeta, quoteResponse } of allTradesInBatch) {
117
+ // Create a new history item for each trade, keyed by quoteId or txMetaId
118
+ if (index > 0 || isNested7702BatchTx) {
119
+ const historyKey = isNested7702BatchTx
120
+ ? getHistoryKeyForQuote(tradeWithMetadata)
121
+ : tradeWithMetadata.txMeta.id;
122
+ const bridgeTxMeta = isNested7702BatchTx
123
+ ? undefined
124
+ : tradeWithMetadata.txMeta;
97
125
  yield {
98
126
  type: SubmitStep.AddHistoryItem,
99
127
  payload: {
100
- historyKey: txMeta.id,
101
- quoteResponse,
128
+ historyKey,
129
+ quoteResponse: tradeWithMetadata.quoteResponse,
102
130
  batchSellData: batchSellTrades,
103
- bridgeTxMeta: txMeta,
131
+ bridgeTxMeta,
104
132
  },
105
133
  };
106
134
  }
@@ -1 +1 @@
1
- {"version":3,"file":"batch-sell-strategy.js","sourceRoot":"","sources":["../../src/strategy/batch-sell-strategy.ts"],"names":[],"mappings":"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","sourcesContent":["import { BatchSellTradesResponse, TxData } from '@metamask/bridge-controller';\nimport {\n TransactionMeta,\n TransactionType,\n} from '@metamask/transaction-controller';\n\nimport { QuoteAndTxMetadata } from '../types.js';\nimport {\n findAllTransactionsInBatch,\n getAddTransactionBatchParams,\n hasNestedSwapTransactions,\n is7702Tx,\n isTradeTx,\n shouldDisable7702,\n toQuoteAndTxMetadataBatch,\n} from '../utils/transaction.js';\nimport { SubmitStep } from './types.js';\nimport type { SubmitStrategyParams, SubmitStepResult } from './types.js';\n\nconst getHistoryKeyForQuote = ({\n quoteResponse: { quoteId, quote },\n}: QuoteAndTxMetadata): string => quoteId ?? quote.requestId;\n\n/**\n * Submits batch-sell transactions to the TransactionController\n *\n * @param args - The parameters for the transaction\n * @yields The approvalMeta and tradeMeta for the first batch sell transaction\n */\nexport async function* submitBatchSellHandler(\n args: SubmitStrategyParams<TxData, BatchSellTradesResponse>,\n): AsyncGenerator<SubmitStepResult, void, void> {\n const {\n requireApproval,\n quoteResponses,\n messenger,\n addTransactionBatchFn,\n isDelegatedAccount,\n batchSellTrades,\n batchId: batchIdParam,\n } = args;\n\n const tradeData = toQuoteAndTxMetadataBatch({\n quoteResponses,\n batchSellTrades,\n });\n\n const { gasIncluded7702, gasIncluded, gasSponsored } = batchSellTrades;\n\n const gasFeeToken = tradeData.find(\n ({ type }) => type === TransactionType.tokenMethodTransfer,\n )?.tx.to;\n\n const transactionParams = await getAddTransactionBatchParams({\n messenger,\n tradeData,\n requireApproval,\n isDelegatedAccount,\n // Tx success/failure is independent of other txs in the batch\n atomic: false,\n disable7702: shouldDisable7702(\n gasIncluded7702,\n gasIncluded,\n isDelegatedAccount,\n ),\n isGasFeeSponsored: gasSponsored,\n isGasFeeIncluded: Boolean(gasIncluded7702),\n batchId: batchIdParam,\n skipInitialGasEstimate: gasIncluded7702\n ? isDelegatedAccount\n : Boolean(gasFeeToken),\n excludeNativeTokenForFee: !gasFeeToken,\n });\n\n // Submit the batch to the TransactionController\n const { batchId } = await addTransactionBatchFn(transactionParams);\n\n // Find all batch transaction metas and add them to history\n const allTradesInBatch = findAllTransactionsInBatch({\n messenger,\n batchId,\n tradeData,\n }).filter(\n (metadata): metadata is QuoteAndTxMetadata & { txMeta: TransactionMeta } =>\n isTradeTx(metadata.type) && metadata.txMeta !== undefined,\n );\n\n // This is either the delegation tx or the first STX swap in the batch\n const firstTradeWithMetadata = allTradesInBatch.find(\n ({ txMeta }) =>\n txMeta?.type &&\n (isTradeTx(txMeta.type) || hasNestedSwapTransactions(txMeta)),\n );\n const firstTradeMeta = firstTradeWithMetadata?.txMeta;\n if (!firstTradeMeta) {\n throw new Error(\n 'Failed to add BatchSell trade to history: txMeta not found',\n );\n }\n\n yield {\n type: SubmitStep.SetTradeMeta,\n payload: {\n tradeMeta: firstTradeMeta,\n },\n };\n\n // Each quote must be reported to the reconsiler service (through QuoteStatusManager) with the hash of the tx that\n // actually executed it. So the number of distinct txs the batch produced\n // decides how quotes are tracked:\n // - one tx (atomic 7702 batch): all quotes share the single hash.\n // - many txs (e.g. STX/sendBundle): each quote has its own hash.\n // `is7702Tx` only means the account is delegated (true even for many-tx\n // batches), so count the unique txs instead.\n const isSingleBatchTx =\n new Set(allTradesInBatch.map(({ txMeta }) => txMeta.id)).size === 1;\n\n // Nested/7702 batch\n if (\n isSingleBatchTx &&\n (is7702Tx(firstTradeMeta) || hasNestedSwapTransactions(firstTradeMeta))\n ) {\n const quoteIds = Array.from(\n new Set(allTradesInBatch.map(getHistoryKeyForQuote)),\n );\n\n // Create 1 history item for the parent tx, keyed by the txMeta.id\n yield {\n type: SubmitStep.AddHistoryItem,\n payload: {\n historyKey: firstTradeMeta.id,\n quoteResponse: firstTradeWithMetadata.quoteResponse,\n batchSellData: batchSellTrades,\n quoteIds,\n bridgeTxMeta: firstTradeMeta,\n },\n };\n // Then create a new history item for each nested trade, keyed by quoteId/requestId\n for (const tradeWithMetadata of allTradesInBatch) {\n const { quoteResponse } = tradeWithMetadata;\n\n yield {\n type: SubmitStep.AddHistoryItem,\n payload: {\n historyKey: getHistoryKeyForQuote(tradeWithMetadata),\n quoteResponse,\n batchSellData: batchSellTrades,\n },\n };\n }\n } else {\n // Each trade has its own txMeta if not submitted via 7702\n // Create a new history item for each one, keyed by txMeta.id\n // Note that the approvalTxId is not tracked in history\n for (const { txMeta, quoteResponse } of allTradesInBatch) {\n yield {\n type: SubmitStep.AddHistoryItem,\n payload: {\n historyKey: txMeta.id,\n quoteResponse,\n batchSellData: batchSellTrades,\n bridgeTxMeta: txMeta,\n },\n };\n }\n }\n}\n"]}
1
+ {"version":3,"file":"batch-sell-strategy.js","sourceRoot":"","sources":["../../src/strategy/batch-sell-strategy.ts"],"names":[],"mappings":"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","sourcesContent":["import { BatchSellTradesResponse, TxData } from '@metamask/bridge-controller';\nimport {\n generateBatchId,\n TransactionMeta,\n TransactionType,\n} from '@metamask/transaction-controller';\n\nimport { QuoteAndTxMetadata } from '../types.js';\nimport {\n findAllTransactionsInBatch,\n getAddTransactionBatchParams,\n hasNestedSwapTransactions,\n is7702Tx,\n isTradeTx,\n shouldDisable7702,\n toQuoteAndTxMetadataBatch,\n} from '../utils/transaction.js';\nimport { SubmitStep } from './types.js';\nimport type { SubmitStrategyParams, SubmitStepResult } from './types.js';\n\nconst getHistoryKeyForQuote = ({\n quoteResponse: { quoteId, quote },\n}: QuoteAndTxMetadata): string => quoteId ?? quote.requestId;\n\n/**\n * Submits batch-sell transactions to the TransactionController\n *\n * @param args - The parameters for the transaction\n * @yields The approvalMeta and tradeMeta for the first batch sell transaction\n */\nexport async function* submitBatchSellHandler(\n args: SubmitStrategyParams<TxData, BatchSellTradesResponse>,\n): AsyncGenerator<SubmitStepResult, void, void> {\n const {\n requireApproval,\n quoteResponses,\n messenger,\n addTransactionBatchFn,\n isDelegatedAccount,\n batchSellTrades,\n batchId: batchIdParam,\n } = args;\n\n const tradeData = toQuoteAndTxMetadataBatch({\n quoteResponses,\n batchSellTrades,\n });\n\n const { gasIncluded7702, gasIncluded, gasSponsored } = batchSellTrades;\n\n const gasFeeToken = tradeData.find(\n ({ type }) => type === TransactionType.tokenMethodTransfer,\n )?.tx.to;\n\n const batchId = batchIdParam ?? generateBatchId();\n\n // Create 1 history item for the parent tx or first quote, keyed by the batchId\n yield {\n type: SubmitStep.AddHistoryItem,\n payload: {\n historyKey: batchId,\n quoteResponse: tradeData[0].quoteResponse,\n batchSellData: batchSellTrades,\n bridgeTxMeta: {\n batchId,\n },\n },\n };\n\n const transactionParams = await getAddTransactionBatchParams({\n messenger,\n tradeData,\n requireApproval,\n isDelegatedAccount,\n // Tx success/failure is independent of other txs in the batch\n atomic: false,\n disable7702: shouldDisable7702(\n gasIncluded7702,\n gasIncluded,\n isDelegatedAccount,\n ),\n isGasFeeSponsored: gasSponsored,\n isGasFeeIncluded: Boolean(gasIncluded7702),\n batchId,\n skipInitialGasEstimate: gasIncluded7702\n ? isDelegatedAccount\n : Boolean(gasFeeToken),\n excludeNativeTokenForFee: !gasFeeToken,\n });\n\n // Submit the batch to the TransactionController\n try {\n await addTransactionBatchFn(transactionParams);\n } catch (error) {\n const allTradesInBatch = findAllTransactionsInBatch({\n messenger,\n batchId,\n tradeData,\n });\n // Propagate the error if tx has not been added to the TransactionController\n if (!allTradesInBatch.some(({ txMeta }) => txMeta)) {\n throw error;\n }\n }\n\n // Find all batch transaction metas and add them to history\n const allTradesInBatch = findAllTransactionsInBatch({\n messenger,\n batchId,\n tradeData,\n }).filter(\n (metadata): metadata is QuoteAndTxMetadata & { txMeta: TransactionMeta } =>\n isTradeTx(metadata.type) && metadata.txMeta !== undefined,\n );\n\n // This is either the delegation tx or the first STX swap in the batch\n const firstTradeWithMetadata = allTradesInBatch.find(\n ({ txMeta }) =>\n txMeta?.type &&\n (isTradeTx(txMeta.type) || hasNestedSwapTransactions(txMeta)),\n );\n const firstTradeMeta = firstTradeWithMetadata?.txMeta;\n if (!firstTradeMeta) {\n throw new Error(\n 'Failed to add BatchSell trade to history: txMeta not found',\n );\n }\n\n yield {\n type: SubmitStep.SetTradeMeta,\n payload: {\n tradeMeta: firstTradeMeta,\n },\n };\n\n // Each quote must be reported to the reconsiler service (through QuoteStatusManager) with the hash of the tx that\n // actually executed it. So the number of distinct txs the batch produced\n // decides how quotes are tracked:\n // - one tx (atomic 7702 batch): all quotes share the single hash.\n // - many txs (e.g. STX/sendBundle): each quote has its own hash.\n // `is7702Tx` only means the account is delegated (true even for many-tx\n // batches), so count the unique txs instead.\n const isSingleBatchTx =\n new Set(allTradesInBatch.map(({ txMeta }) => txMeta.id)).size === 1;\n const isNested7702BatchTx =\n isSingleBatchTx &&\n (is7702Tx(firstTradeMeta) || hasNestedSwapTransactions(firstTradeMeta));\n\n // Each trade has its own txMeta if not submitted via 7702\n // Create a new history item for each one, keyed by txMeta.id\n // Note that the approvalTxId is not tracked in history\n for (const [index, tradeWithMetadata] of allTradesInBatch.entries()) {\n // Rekey the initial trade\n if (index === 0) {\n const quoteIds = isNested7702BatchTx\n ? Array.from(new Set(allTradesInBatch.map(getHistoryKeyForQuote)))\n : undefined;\n const initialTrade = isNested7702BatchTx\n ? firstTradeWithMetadata\n : tradeWithMetadata;\n yield {\n type: SubmitStep.RekeyHistoryItem,\n payload: {\n oldHistoryKey: batchId,\n newHistoryKey: initialTrade.txMeta.id,\n historyItemOverrides: {\n quote: initialTrade.quoteResponse.quote,\n quoteIds,\n },\n tradeMeta: initialTrade.txMeta,\n },\n };\n }\n // Create a new history item for each trade, keyed by quoteId or txMetaId\n if (index > 0 || isNested7702BatchTx) {\n const historyKey = isNested7702BatchTx\n ? getHistoryKeyForQuote(tradeWithMetadata)\n : tradeWithMetadata.txMeta.id;\n const bridgeTxMeta = isNested7702BatchTx\n ? undefined\n : tradeWithMetadata.txMeta;\n yield {\n type: SubmitStep.AddHistoryItem,\n payload: {\n historyKey,\n quoteResponse: tradeWithMetadata.quoteResponse,\n batchSellData: batchSellTrades,\n bridgeTxMeta,\n },\n };\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"batch-strategy.d.ts","sourceRoot":"","sources":["../../src/strategy/batch-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAW1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEzE;;;;;GAKG;AACH,wBAAuB,kBAAkB,CACvC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,GACjC,cAAc,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,CAAC,CA6E9C"}
1
+ {"version":3,"file":"batch-strategy.d.ts","sourceRoot":"","sources":["../../src/strategy/batch-strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAa1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEzE;;;;;GAKG;AACH,wBAAuB,kBAAkB,CACvC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,GACjC,cAAc,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,CAAC,CAqG9C"}
@@ -1,3 +1,4 @@
1
+ import { generateBatchId } from '@metamask/transaction-controller';
1
2
  import { findAllTransactionsInBatch, getAddTransactionBatchParams, isApprovalTx, isTradeTx, shouldDisable7702, toQuoteAndTxMetadata, } from '../utils/transaction.js';
2
3
  import { SubmitStep } from './types.js';
3
4
  /**
@@ -12,6 +13,17 @@ export async function* submitBatchHandler(args) {
12
13
  quoteResponse,
13
14
  isBridgeTx,
14
15
  });
16
+ const batchId = generateBatchId();
17
+ yield {
18
+ type: SubmitStep.AddHistoryItem,
19
+ payload: {
20
+ historyKey: batchId,
21
+ quoteResponse,
22
+ bridgeTxMeta: {
23
+ batchId,
24
+ },
25
+ },
26
+ };
15
27
  const transactionParams = await getAddTransactionBatchParams({
16
28
  tradeData,
17
29
  requireApproval,
@@ -21,13 +33,28 @@ export async function* submitBatchHandler(args) {
21
33
  disable7702: shouldDisable7702(quoteResponse.quote.gasIncluded7702, quoteResponse.quote.gasIncluded, isDelegatedAccount),
22
34
  isGasFeeSponsored: Boolean(quoteResponse.quote.gasSponsored),
23
35
  isGasFeeIncluded: Boolean(quoteResponse.quote.gasIncluded7702),
24
- });
25
- const { batchId } = await addTransactionBatchFn(transactionParams);
26
- const quoteAndTxMetas = findAllTransactionsInBatch({
27
- messenger,
28
36
  batchId,
29
- tradeData,
30
37
  });
38
+ let quoteAndTxMetas = [];
39
+ try {
40
+ await addTransactionBatchFn(transactionParams);
41
+ quoteAndTxMetas = findAllTransactionsInBatch({
42
+ messenger,
43
+ batchId,
44
+ tradeData,
45
+ });
46
+ }
47
+ catch (error) {
48
+ quoteAndTxMetas = findAllTransactionsInBatch({
49
+ messenger,
50
+ batchId,
51
+ tradeData,
52
+ });
53
+ // If txMeta has not been added to the TransactionController, propagate the error
54
+ if (!quoteAndTxMetas.some(({ txMeta }) => txMeta)) {
55
+ throw error;
56
+ }
57
+ }
31
58
  yield {
32
59
  type: SubmitStep.UpdateBatchTransactions,
33
60
  payload: {
@@ -44,16 +71,14 @@ export async function* submitBatchHandler(args) {
44
71
  payload: { tradeMeta },
45
72
  };
46
73
  yield {
47
- type: SubmitStep.AddHistoryItem,
74
+ type: SubmitStep.RekeyHistoryItem,
48
75
  payload: {
49
- historyKey: tradeMeta.id,
50
- approvalTxId: approvalMeta?.id,
51
- bridgeTxMeta: {
52
- id: tradeMeta.id,
53
- hash: tradeMeta.hash,
54
- batchId: tradeMeta.batchId,
76
+ oldHistoryKey: batchId,
77
+ newHistoryKey: tradeMeta.id,
78
+ historyItemOverrides: {
79
+ approvalTxId: approvalMeta?.id,
55
80
  },
56
- quoteResponse,
81
+ tradeMeta,
57
82
  },
58
83
  };
59
84
  }
@@ -1 +1 @@
1
- {"version":3,"file":"batch-strategy.js","sourceRoot":"","sources":["../../src/strategy/batch-strategy.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,YAAY,EACZ,SAAS,EACT,iBAAiB,EACjB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGxC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,kBAAkB,CACvC,IAAkC;IAElC,MAAM,EACJ,eAAe,EACf,cAAc,EAAE,CAAC,aAAa,CAAC,EAC/B,SAAS,EACT,UAAU,EACV,qBAAqB,EACrB,kBAAkB,GACnB,GAAG,IAAI,CAAC;IAET,MAAM,SAAS,GAAG,oBAAoB,CAAC;QACrC,aAAa;QACb,UAAU;KACX,CAAC,CAAC;IAEH,MAAM,iBAAiB,GAAG,MAAM,4BAA4B,CAAC;QAC3D,SAAS;QACT,eAAe;QACf,kBAAkB;QAClB,SAAS;QACT,MAAM,EAAE,IAAI;QACZ,WAAW,EAAE,iBAAiB,CAC5B,aAAa,CAAC,KAAK,CAAC,eAAe,EACnC,aAAa,CAAC,KAAK,CAAC,WAAW,EAC/B,kBAAkB,CACnB;QACD,iBAAiB,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,YAAY,CAAC;QAC5D,gBAAgB,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,eAAe,CAAC;KAC/D,CAAC,CAAC;IAEH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,qBAAqB,CAAC,iBAAiB,CAAC,CAAC;IAEnE,MAAM,eAAe,GAAG,0BAA0B,CAAC;QACjD,SAAS;QACT,OAAO;QACP,SAAS;KACV,CAAC,CAAC;IAEH,MAAM;QACJ,IAAI,EAAE,UAAU,CAAC,uBAAuB;QACxC,OAAO,EAAE;YACP,eAAe;SAChB;KACF,CAAC;IAEF,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,CACpC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,MAAM,CAChD,EAAE,MAAM,CAAC;IAEV,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CACvC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,MAAM,CACnD,EAAE,MAAM,CAAC;IAEV,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,0EAA0E,CAC3E,CAAC;IACJ,CAAC;IAED,MAAM;QACJ,IAAI,EAAE,UAAU,CAAC,YAAY;QAC7B,OAAO,EAAE,EAAE,SAAS,EAAE;KACvB,CAAC;IAEF,MAAM;QACJ,IAAI,EAAE,UAAU,CAAC,cAAc;QAC/B,OAAO,EAAE;YACP,UAAU,EAAE,SAAS,CAAC,EAAE;YACxB,YAAY,EAAE,YAAY,EAAE,EAAE;YAC9B,YAAY,EAAE;gBACZ,EAAE,EAAE,SAAS,CAAC,EAAE;gBAChB,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,OAAO,EAAE,SAAS,CAAC,OAAO;aAC3B;YACD,aAAa;SACd;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type { TxData } from '@metamask/bridge-controller';\n\nimport {\n findAllTransactionsInBatch,\n getAddTransactionBatchParams,\n isApprovalTx,\n isTradeTx,\n shouldDisable7702,\n toQuoteAndTxMetadata,\n} from '../utils/transaction.js';\nimport { SubmitStep } from './types.js';\nimport type { SubmitStrategyParams, SubmitStepResult } from './types.js';\n\n/**\n * Submits batched EVM transactions to the TransactionController\n *\n * @param args - The parameters for the transaction\n * @yields The approvalMeta and tradeMeta for the batched transaction\n */\nexport async function* submitBatchHandler(\n args: SubmitStrategyParams<TxData>,\n): AsyncGenerator<SubmitStepResult, void, void> {\n const {\n requireApproval,\n quoteResponses: [quoteResponse],\n messenger,\n isBridgeTx,\n addTransactionBatchFn,\n isDelegatedAccount,\n } = args;\n\n const tradeData = toQuoteAndTxMetadata({\n quoteResponse,\n isBridgeTx,\n });\n\n const transactionParams = await getAddTransactionBatchParams({\n tradeData,\n requireApproval,\n isDelegatedAccount,\n messenger,\n atomic: true,\n disable7702: shouldDisable7702(\n quoteResponse.quote.gasIncluded7702,\n quoteResponse.quote.gasIncluded,\n isDelegatedAccount,\n ),\n isGasFeeSponsored: Boolean(quoteResponse.quote.gasSponsored),\n isGasFeeIncluded: Boolean(quoteResponse.quote.gasIncluded7702),\n });\n\n const { batchId } = await addTransactionBatchFn(transactionParams);\n\n const quoteAndTxMetas = findAllTransactionsInBatch({\n messenger,\n batchId,\n tradeData,\n });\n\n yield {\n type: SubmitStep.UpdateBatchTransactions,\n payload: {\n quoteAndTxMetas,\n },\n };\n\n const tradeMeta = quoteAndTxMetas.find(\n ({ type, txMeta }) => isTradeTx(type) && txMeta,\n )?.txMeta;\n\n const approvalMeta = quoteAndTxMetas.find(\n ({ type, txMeta }) => isApprovalTx(type) && txMeta,\n )?.txMeta;\n\n if (!tradeMeta) {\n throw new Error(\n 'Failed to update cross-chain swap transaction batch: tradeMeta not found',\n );\n }\n\n yield {\n type: SubmitStep.SetTradeMeta,\n payload: { tradeMeta },\n };\n\n yield {\n type: SubmitStep.AddHistoryItem,\n payload: {\n historyKey: tradeMeta.id,\n approvalTxId: approvalMeta?.id,\n bridgeTxMeta: {\n id: tradeMeta.id,\n hash: tradeMeta.hash,\n batchId: tradeMeta.batchId,\n },\n quoteResponse,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"batch-strategy.js","sourceRoot":"","sources":["../../src/strategy/batch-strategy.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TxData } from '@metamask/bridge-controller';\nimport { generateBatchId } from '@metamask/transaction-controller';\n\nimport type { QuoteAndTxMetadata } from '../types.js';\nimport {\n findAllTransactionsInBatch,\n getAddTransactionBatchParams,\n isApprovalTx,\n isTradeTx,\n shouldDisable7702,\n toQuoteAndTxMetadata,\n} from '../utils/transaction.js';\nimport { SubmitStep } from './types.js';\nimport type { SubmitStrategyParams, SubmitStepResult } from './types.js';\n\n/**\n * Submits batched EVM transactions to the TransactionController\n *\n * @param args - The parameters for the transaction\n * @yields The approvalMeta and tradeMeta for the batched transaction\n */\nexport async function* submitBatchHandler(\n args: SubmitStrategyParams<TxData>,\n): AsyncGenerator<SubmitStepResult, void, void> {\n const {\n requireApproval,\n quoteResponses: [quoteResponse],\n messenger,\n isBridgeTx,\n addTransactionBatchFn,\n isDelegatedAccount,\n } = args;\n\n const tradeData = toQuoteAndTxMetadata({\n quoteResponse,\n isBridgeTx,\n });\n\n const batchId = generateBatchId();\n\n yield {\n type: SubmitStep.AddHistoryItem,\n payload: {\n historyKey: batchId,\n quoteResponse,\n bridgeTxMeta: {\n batchId,\n },\n },\n };\n\n const transactionParams = await getAddTransactionBatchParams({\n tradeData,\n requireApproval,\n isDelegatedAccount,\n messenger,\n atomic: true,\n disable7702: shouldDisable7702(\n quoteResponse.quote.gasIncluded7702,\n quoteResponse.quote.gasIncluded,\n isDelegatedAccount,\n ),\n isGasFeeSponsored: Boolean(quoteResponse.quote.gasSponsored),\n isGasFeeIncluded: Boolean(quoteResponse.quote.gasIncluded7702),\n batchId,\n });\n\n let quoteAndTxMetas: QuoteAndTxMetadata[] = [];\n try {\n await addTransactionBatchFn(transactionParams);\n quoteAndTxMetas = findAllTransactionsInBatch({\n messenger,\n batchId,\n tradeData,\n });\n } catch (error) {\n quoteAndTxMetas = findAllTransactionsInBatch({\n messenger,\n batchId,\n tradeData,\n });\n // If txMeta has not been added to the TransactionController, propagate the error\n if (!quoteAndTxMetas.some(({ txMeta }) => txMeta)) {\n throw error;\n }\n }\n\n yield {\n type: SubmitStep.UpdateBatchTransactions,\n payload: {\n quoteAndTxMetas,\n },\n };\n\n const tradeMeta = quoteAndTxMetas.find(\n ({ type, txMeta }) => isTradeTx(type) && txMeta,\n )?.txMeta;\n\n const approvalMeta = quoteAndTxMetas.find(\n ({ type, txMeta }) => isApprovalTx(type) && txMeta,\n )?.txMeta;\n\n if (!tradeMeta) {\n throw new Error(\n 'Failed to update cross-chain swap transaction batch: tradeMeta not found',\n );\n }\n\n yield {\n type: SubmitStep.SetTradeMeta,\n payload: { tradeMeta },\n };\n\n yield {\n type: SubmitStep.RekeyHistoryItem,\n payload: {\n oldHistoryKey: batchId,\n newHistoryKey: tradeMeta.id,\n historyItemOverrides: {\n approvalTxId: approvalMeta?.id,\n },\n tradeMeta,\n },\n };\n}\n"]}
@@ -1,33 +1,7 @@
1
1
  import type { TxData } from '@metamask/bridge-controller';
2
- import { TransactionMeta, TransactionType } from '@metamask/transaction-controller';
3
- import { BridgeStatusControllerMessenger } from '../types.js';
2
+ import { TransactionMeta } from '@metamask/transaction-controller';
4
3
  import type { SubmitStrategyParams, SubmitStepResult } from './types.js';
5
- /**
6
- * Submits a single tx to the TransactionController and returns the txMetaId
7
- *
8
- * @param args - The parameters for the transaction
9
- * @param args.transactionType - The type of transaction to submit
10
- * @param args.trade - The trade data to confirm
11
- * @param args.requireApproval - Whether to require approval for the transaction
12
- * @param args.txFee - Optional gas fee parameters from the quote (used when gasIncluded is true)
13
- * @param args.txFee.maxFeePerGas - The maximum fee per gas from the quote
14
- * @param args.txFee.maxPriorityFeePerGas - The maximum priority fee per gas from the quote
15
- * @param args.actionId - Optional actionId for pre-submission history (if not provided, one is generated)
16
- * @param args.messenger - The messenger to use for the transaction
17
- * @returns The transaction meta
18
- */
19
- export declare const handleSingleTx: ({ messenger, trade, transactionType, requireApproval, txFee, actionId, }: {
20
- messenger: BridgeStatusControllerMessenger;
21
- transactionType: TransactionType;
22
- trade: TxData;
23
- requireApproval?: boolean;
24
- txFee?: {
25
- maxFeePerGas: string;
26
- maxPriorityFeePerGas: string;
27
- };
28
- actionId?: string;
29
- }) => Promise<TransactionMeta>;
30
- export declare const handleEvmApprovals: (args: SubmitStrategyParams) => Promise<string | undefined>;
4
+ export declare const handleEvmApprovals: (args: SubmitStrategyParams, actionId?: string) => Promise<TransactionMeta | undefined>;
31
5
  /**
32
6
  * Sequentially submits EVM resetApproval, approval and trade transactions through the TransactionController.
33
7
  *
@@ -1 +1 @@
1
- {"version":3,"file":"evm-strategy.d.ts","sourceRoot":"","sources":["../../src/strategy/evm-strategy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EACL,eAAe,EACf,eAAe,EAChB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,+BAA+B,EAAE,MAAM,aAAa,CAAC;AAa9D,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEzE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,6EAQxB;IACD,SAAS,EAAE,+BAA+B,CAAC;IAC3C,eAAe,EAAE,eAAe,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,oBAAoB,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,KAAG,OAAO,CAAC,eAAe,CAgC1B,CAAC;AA2CF,eAAO,MAAM,kBAAkB,SAAgB,oBAAoB,gCAIhE,CAAC;AAEJ;;;;;GAKG;AACH,wBAAuB,gBAAgB,CACrC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,GACjC,cAAc,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,CAAC,CAqE9C"}
1
+ {"version":3,"file":"evm-strategy.d.ts","sourceRoot":"","sources":["../../src/strategy/evm-strategy.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EACL,eAAe,EAEhB,MAAM,kCAAkC,CAAC;AAgB1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA4GzE,eAAO,MAAM,kBAAkB,SACvB,oBAAoB,aACf,MAAM,yCAKhB,CAAC;AAEJ;;;;;GAKG;AACH,wBAAuB,gBAAgB,CACrC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,GACjC,cAAc,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,CAAC,CA0F9C"}
@@ -5,7 +5,7 @@ import { TransactionType, } from '@metamask/transaction-controller';
5
5
  import { getAccountByAddress } from '../utils/accounts.js';
6
6
  import { getNetworkClientIdByChainId } from '../utils/network.js';
7
7
  import { getApprovalTraceParams } from '../utils/trace.js';
8
- import { addTransaction, generateActionId, handleApprovalDelay, handleMobileHardwareWalletDelay, toTransactionParams, waitForTxConfirmation, } from '../utils/transaction.js';
8
+ import { addTransaction, generateActionId, getTransactionMetaByActionId, handleApprovalDelay, handleMobileHardwareWalletDelay, toTransactionParams, waitForTxConfirmation, } from '../utils/transaction.js';
9
9
  import { SubmitStep } from './types.js';
10
10
  /**
11
11
  * Submits a single tx to the TransactionController and returns the txMetaId
@@ -21,7 +21,7 @@ import { SubmitStep } from './types.js';
21
21
  * @param args.messenger - The messenger to use for the transaction
22
22
  * @returns The transaction meta
23
23
  */
24
- export const handleSingleTx = async ({ messenger, trade, transactionType, requireApproval = false, txFee,
24
+ const handleSingleTx = async ({ messenger, trade, transactionType, requireApproval = false, txFee,
25
25
  // Use provided actionId (for pre-submission history) or generate one
26
26
  actionId = generateActionId(), }) => {
27
27
  const selectedAccount = getAccountByAddress(messenger, trade.from);
@@ -47,10 +47,11 @@ actionId = generateActionId(), }) => {
47
47
  * But only the approval's txMetaId will be returned.
48
48
  *
49
49
  * @param args - The parameters for the submission flow
50
+ * @param actionId - The actionId for the approval transaction
50
51
  *
51
- * @returns The approvalTxId of the approval transaction
52
+ * @returns The approval txMeta of the approval transaction
52
53
  */
53
- const approve = async (args) => {
54
+ const approve = async (args, actionId) => {
54
55
  const { quoteResponses: [quoteResponse], isBridgeTx, } = args;
55
56
  const { approval, resetApproval } = quoteResponse;
56
57
  if (!approval || !isEvmTxData(approval)) {
@@ -71,11 +72,12 @@ const approve = async (args) => {
71
72
  ...args,
72
73
  transactionType,
73
74
  trade: approval,
75
+ actionId,
74
76
  });
75
- return approvalTxMeta?.id;
77
+ return approvalTxMeta;
76
78
  }
77
79
  };
78
- export const handleEvmApprovals = async (args) => await args.traceFn(getApprovalTraceParams(args.quoteResponses[0], args.isStxEnabled), async () => await approve(args));
80
+ export const handleEvmApprovals = async (args, actionId) => await args.traceFn(getApprovalTraceParams(args.quoteResponses[0], args.isStxEnabled), async () => await approve(args, actionId));
79
81
  /**
80
82
  * Sequentially submits EVM resetApproval, approval and trade transactions through the TransactionController.
81
83
  *
@@ -84,19 +86,7 @@ export const handleEvmApprovals = async (args) => await args.traceFn(getApproval
84
86
  */
85
87
  export async function* submitEvmHandler(args) {
86
88
  const { quoteResponses: [quoteResponse], requireApproval, isBridgeTx, } = args;
87
- // Submit resetApproval and approval transactions if present
88
- const approvalTxId = await handleEvmApprovals(args);
89
- // Delay after approval
90
- if (approvalTxId) {
91
- await handleApprovalDelay(quoteResponse.quote.srcChainId);
92
- }
93
- // Hardware-wallet delay first (Ledger second-prompt spacing), then wait for
94
- // on-chain approval confirmation so swap gas estimation runs after allowance is set.
95
- await handleMobileHardwareWalletDelay(requireApproval);
96
- if (requireApproval && approvalTxId) {
97
- await waitForTxConfirmation(args.messenger, approvalTxId);
98
- }
99
- // Generate trade actionId for pre-submission history
89
+ // Generate actionId for pre-submission history
100
90
  const actionId = generateActionId();
101
91
  // Add pre-submission history keyed by actionId
102
92
  // This ensures we have quote data available if transaction fails during submission
@@ -104,40 +94,73 @@ export async function* submitEvmHandler(args) {
104
94
  type: SubmitStep.AddHistoryItem,
105
95
  payload: {
106
96
  historyKey: actionId,
107
- approvalTxId,
108
97
  actionId,
109
98
  quoteResponse,
110
99
  },
111
100
  };
101
+ // Submit resetApproval and approval transactions if present
102
+ const approvalTxMeta = await handleEvmApprovals(args, actionId);
103
+ const approvalTxId = approvalTxMeta?.id;
104
+ let tradeActionId = actionId;
105
+ // Delay after approval
106
+ if (approvalTxId) {
107
+ // Generate a new actionId for the trade transaction since approval used the first one
108
+ tradeActionId = generateActionId();
109
+ yield {
110
+ type: SubmitStep.RekeyHistoryItem,
111
+ payload: {
112
+ oldHistoryKey: actionId,
113
+ newHistoryKey: tradeActionId,
114
+ historyItemOverrides: {
115
+ approvalTxId,
116
+ },
117
+ },
118
+ };
119
+ await handleApprovalDelay(quoteResponse.quote.srcChainId);
120
+ }
121
+ // Hardware-wallet delay first (Ledger second-prompt spacing), then wait for
122
+ // on-chain approval confirmation so swap gas estimation runs after allowance is set.
123
+ await handleMobileHardwareWalletDelay(requireApproval);
124
+ if (requireApproval && approvalTxId) {
125
+ await waitForTxConfirmation(args.messenger, approvalTxId);
126
+ }
112
127
  const transactionType = isBridgeTx
113
128
  ? TransactionType.bridge
114
129
  : TransactionType.swap;
115
- const tradeMeta = await handleSingleTx({
116
- ...args,
117
- transactionType,
118
- trade: quoteResponse.trade,
119
- // TODO figure out if this is needed
120
- // Pass txFee when gasIncluded is true to use the quote's gas fees
121
- // instead of re-estimating (which would fail for max native token swaps)
122
- txFee: quoteResponse.quote.gasIncluded
123
- ? quoteResponse.quote.feeData.txFee
124
- : undefined,
125
- actionId,
126
- });
130
+ let tradeMeta;
131
+ try {
132
+ tradeMeta = await handleSingleTx({
133
+ ...args,
134
+ transactionType,
135
+ trade: quoteResponse.trade,
136
+ // TODO figure out if this is needed
137
+ // Pass txFee when gasIncluded is true to use the quote's gas fees
138
+ // instead of re-estimating (which would fail for max native token swaps)
139
+ txFee: quoteResponse.quote.gasIncluded
140
+ ? quoteResponse.quote.feeData.txFee
141
+ : undefined,
142
+ actionId: tradeActionId,
143
+ });
144
+ }
145
+ catch (error) {
146
+ // Silence the error if tx has been added to the TransactionController to prevent duplicate Failed events
147
+ tradeMeta = getTransactionMetaByActionId(args.messenger, tradeActionId);
148
+ if (!tradeMeta) {
149
+ throw error;
150
+ }
151
+ }
152
+ yield {
153
+ type: SubmitStep.SetTradeMeta,
154
+ payload: { tradeMeta },
155
+ };
127
156
  // Use the tradeMeta's id as history key
128
157
  yield {
129
158
  type: SubmitStep.RekeyHistoryItem,
130
159
  payload: {
131
- oldHistoryKey: actionId,
160
+ oldHistoryKey: tradeActionId,
132
161
  newHistoryKey: tradeMeta.id,
133
162
  tradeMeta,
134
163
  },
135
164
  };
136
- yield {
137
- type: SubmitStep.SetTradeMeta,
138
- payload: {
139
- tradeMeta,
140
- },
141
- };
142
165
  }
143
166
  //# sourceMappingURL=evm-strategy.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"evm-strategy.js","sourceRoot":"","sources":["../../src/strategy/evm-strategy.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable consistent-return */\n/* eslint-disable @typescript-eslint/explicit-function-return-type */\nimport { formatChainIdToHex, isEvmTxData } from '@metamask/bridge-controller';\nimport type { TxData } from '@metamask/bridge-controller';\nimport {\n TransactionMeta,\n TransactionType,\n} from '@metamask/transaction-controller';\n\nimport { BridgeStatusControllerMessenger } from '../types.js';\nimport { getAccountByAddress } from '../utils/accounts.js';\nimport { getNetworkClientIdByChainId } from '../utils/network.js';\nimport { getApprovalTraceParams } from '../utils/trace.js';\nimport {\n addTransaction,\n generateActionId,\n handleApprovalDelay,\n handleMobileHardwareWalletDelay,\n toTransactionParams,\n waitForTxConfirmation,\n} from '../utils/transaction.js';\nimport { SubmitStep } from './types.js';\nimport type { SubmitStrategyParams, SubmitStepResult } from './types.js';\n\n/**\n * Submits a single tx to the TransactionController and returns the txMetaId\n *\n * @param args - The parameters for the transaction\n * @param args.transactionType - The type of transaction to submit\n * @param args.trade - The trade data to confirm\n * @param args.requireApproval - Whether to require approval for the transaction\n * @param args.txFee - Optional gas fee parameters from the quote (used when gasIncluded is true)\n * @param args.txFee.maxFeePerGas - The maximum fee per gas from the quote\n * @param args.txFee.maxPriorityFeePerGas - The maximum priority fee per gas from the quote\n * @param args.actionId - Optional actionId for pre-submission history (if not provided, one is generated)\n * @param args.messenger - The messenger to use for the transaction\n * @returns The transaction meta\n */\nexport const handleSingleTx = async ({\n messenger,\n trade,\n transactionType,\n requireApproval = false,\n txFee,\n // Use provided actionId (for pre-submission history) or generate one\n actionId = generateActionId(),\n}: {\n messenger: BridgeStatusControllerMessenger;\n transactionType: TransactionType;\n trade: TxData;\n requireApproval?: boolean;\n txFee?: { maxFeePerGas: string; maxPriorityFeePerGas: string };\n actionId?: string;\n}): Promise<TransactionMeta> => {\n const selectedAccount = getAccountByAddress(messenger, trade.from);\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 = getNetworkClientIdByChainId(messenger, hexChainId);\n\n const requestOptions = {\n actionId,\n networkClientId,\n requireApproval,\n type: transactionType,\n origin: 'metamask',\n isInternal: true,\n };\n\n const transactionParamsWithMaxGas = await toTransactionParams(\n messenger,\n trade,\n networkClientId,\n hexChainId,\n txFee,\n );\n\n return await addTransaction(\n messenger,\n { ...transactionParamsWithMaxGas, from: trade.from },\n requestOptions,\n );\n};\n\n/**\n * Submits the approval and resetApproval transactions through the TransactionController.\n * If there is a resetApproval, it will be submitted first.\n * But only the approval's txMetaId will be returned.\n *\n * @param args - The parameters for the submission flow\n *\n * @returns The approvalTxId of the approval transaction\n */\nconst approve = async (args: SubmitStrategyParams) => {\n const {\n quoteResponses: [quoteResponse],\n isBridgeTx,\n } = args;\n const { approval, resetApproval } = quoteResponse;\n if (!approval || !isEvmTxData(approval)) {\n return;\n }\n\n const transactionType = isBridgeTx\n ? TransactionType.bridgeApproval\n : TransactionType.swapApproval;\n\n if (resetApproval) {\n await handleSingleTx({\n ...args,\n transactionType,\n trade: resetApproval,\n });\n }\n\n if (approval) {\n const approvalTxMeta = await handleSingleTx({\n ...args,\n transactionType,\n trade: approval,\n });\n return approvalTxMeta?.id;\n }\n};\n\nexport const handleEvmApprovals = async (args: SubmitStrategyParams) =>\n await args.traceFn(\n getApprovalTraceParams(args.quoteResponses[0], args.isStxEnabled),\n async () => await approve(args),\n );\n\n/**\n * Sequentially submits EVM resetApproval, approval and trade transactions through the TransactionController.\n *\n * @param args - The parameters for the transaction\n * @yields Data for updating the BridgeStatusController\n */\nexport async function* submitEvmHandler(\n args: SubmitStrategyParams<TxData>,\n): AsyncGenerator<SubmitStepResult, void, void> {\n const {\n quoteResponses: [quoteResponse],\n requireApproval,\n isBridgeTx,\n } = args;\n\n // Submit resetApproval and approval transactions if present\n const approvalTxId = await handleEvmApprovals(args);\n\n // Delay after approval\n if (approvalTxId) {\n await handleApprovalDelay(quoteResponse.quote.srcChainId);\n }\n // Hardware-wallet delay first (Ledger second-prompt spacing), then wait for\n // on-chain approval confirmation so swap gas estimation runs after allowance is set.\n await handleMobileHardwareWalletDelay(requireApproval);\n if (requireApproval && approvalTxId) {\n await waitForTxConfirmation(args.messenger, approvalTxId);\n }\n\n // Generate trade actionId for pre-submission history\n const actionId = generateActionId();\n\n // Add pre-submission history keyed by actionId\n // This ensures we have quote data available if transaction fails during submission\n yield {\n type: SubmitStep.AddHistoryItem,\n payload: {\n historyKey: actionId,\n approvalTxId,\n actionId,\n quoteResponse,\n },\n };\n\n const transactionType = isBridgeTx\n ? TransactionType.bridge\n : TransactionType.swap;\n\n const tradeMeta = await handleSingleTx({\n ...args,\n transactionType,\n trade: quoteResponse.trade,\n // TODO figure out if this is needed\n // Pass txFee when gasIncluded is true to use the quote's gas fees\n // instead of re-estimating (which would fail for max native token swaps)\n txFee: quoteResponse.quote.gasIncluded\n ? quoteResponse.quote.feeData.txFee\n : undefined,\n actionId,\n });\n\n // Use the tradeMeta's id as history key\n yield {\n type: SubmitStep.RekeyHistoryItem,\n payload: {\n oldHistoryKey: actionId,\n newHistoryKey: tradeMeta.id,\n tradeMeta,\n },\n };\n\n yield {\n type: SubmitStep.SetTradeMeta,\n payload: {\n tradeMeta,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"evm-strategy.js","sourceRoot":"","sources":["../../src/strategy/evm-strategy.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable consistent-return */\n/* eslint-disable @typescript-eslint/explicit-function-return-type */\nimport { formatChainIdToHex, isEvmTxData } from '@metamask/bridge-controller';\nimport type { TxData } from '@metamask/bridge-controller';\nimport {\n TransactionMeta,\n TransactionType,\n} from '@metamask/transaction-controller';\n\nimport { BridgeStatusControllerMessenger } from '../types.js';\nimport { getAccountByAddress } from '../utils/accounts.js';\nimport { getNetworkClientIdByChainId } from '../utils/network.js';\nimport { getApprovalTraceParams } from '../utils/trace.js';\nimport {\n addTransaction,\n generateActionId,\n getTransactionMetaByActionId,\n handleApprovalDelay,\n handleMobileHardwareWalletDelay,\n toTransactionParams,\n waitForTxConfirmation,\n} from '../utils/transaction.js';\nimport { SubmitStep } from './types.js';\nimport type { SubmitStrategyParams, SubmitStepResult } from './types.js';\n\n/**\n * Submits a single tx to the TransactionController and returns the txMetaId\n *\n * @param args - The parameters for the transaction\n * @param args.transactionType - The type of transaction to submit\n * @param args.trade - The trade data to confirm\n * @param args.requireApproval - Whether to require approval for the transaction\n * @param args.txFee - Optional gas fee parameters from the quote (used when gasIncluded is true)\n * @param args.txFee.maxFeePerGas - The maximum fee per gas from the quote\n * @param args.txFee.maxPriorityFeePerGas - The maximum priority fee per gas from the quote\n * @param args.actionId - Optional actionId for pre-submission history (if not provided, one is generated)\n * @param args.messenger - The messenger to use for the transaction\n * @returns The transaction meta\n */\nconst handleSingleTx = async ({\n messenger,\n trade,\n transactionType,\n requireApproval = false,\n txFee,\n // Use provided actionId (for pre-submission history) or generate one\n actionId = generateActionId(),\n}: {\n messenger: BridgeStatusControllerMessenger;\n transactionType: TransactionType;\n trade: TxData;\n requireApproval?: boolean;\n txFee?: { maxFeePerGas: string; maxPriorityFeePerGas: string };\n actionId?: string;\n}): Promise<TransactionMeta> => {\n const selectedAccount = getAccountByAddress(messenger, trade.from);\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 = getNetworkClientIdByChainId(messenger, hexChainId);\n\n const requestOptions = {\n actionId,\n networkClientId,\n requireApproval,\n type: transactionType,\n origin: 'metamask',\n isInternal: true,\n };\n\n const transactionParamsWithMaxGas = await toTransactionParams(\n messenger,\n trade,\n networkClientId,\n hexChainId,\n txFee,\n );\n\n return await addTransaction(\n messenger,\n { ...transactionParamsWithMaxGas, from: trade.from },\n requestOptions,\n );\n};\n\n/**\n * Submits the approval and resetApproval transactions through the TransactionController.\n * If there is a resetApproval, it will be submitted first.\n * But only the approval's txMetaId will be returned.\n *\n * @param args - The parameters for the submission flow\n * @param actionId - The actionId for the approval transaction\n *\n * @returns The approval txMeta of the approval transaction\n */\nconst approve = async (args: SubmitStrategyParams, actionId?: string) => {\n const {\n quoteResponses: [quoteResponse],\n isBridgeTx,\n } = args;\n const { approval, resetApproval } = quoteResponse;\n if (!approval || !isEvmTxData(approval)) {\n return;\n }\n\n const transactionType = isBridgeTx\n ? TransactionType.bridgeApproval\n : TransactionType.swapApproval;\n\n if (resetApproval) {\n await handleSingleTx({\n ...args,\n transactionType,\n trade: resetApproval,\n });\n }\n\n if (approval) {\n const approvalTxMeta = await handleSingleTx({\n ...args,\n transactionType,\n trade: approval,\n actionId,\n });\n return approvalTxMeta;\n }\n};\n\nexport const handleEvmApprovals = async (\n args: SubmitStrategyParams,\n actionId?: string,\n) =>\n await args.traceFn(\n getApprovalTraceParams(args.quoteResponses[0], args.isStxEnabled),\n async () => await approve(args, actionId),\n );\n\n/**\n * Sequentially submits EVM resetApproval, approval and trade transactions through the TransactionController.\n *\n * @param args - The parameters for the transaction\n * @yields Data for updating the BridgeStatusController\n */\nexport async function* submitEvmHandler(\n args: SubmitStrategyParams<TxData>,\n): AsyncGenerator<SubmitStepResult, void, void> {\n const {\n quoteResponses: [quoteResponse],\n requireApproval,\n isBridgeTx,\n } = args;\n\n // Generate actionId for pre-submission history\n const actionId = generateActionId();\n\n // Add pre-submission history keyed by actionId\n // This ensures we have quote data available if transaction fails during submission\n yield {\n type: SubmitStep.AddHistoryItem,\n payload: {\n historyKey: actionId,\n actionId,\n quoteResponse,\n },\n };\n\n // Submit resetApproval and approval transactions if present\n const approvalTxMeta = await handleEvmApprovals(args, actionId);\n const approvalTxId = approvalTxMeta?.id;\n\n let tradeActionId = actionId;\n\n // Delay after approval\n if (approvalTxId) {\n // Generate a new actionId for the trade transaction since approval used the first one\n tradeActionId = generateActionId();\n yield {\n type: SubmitStep.RekeyHistoryItem,\n payload: {\n oldHistoryKey: actionId,\n newHistoryKey: tradeActionId,\n historyItemOverrides: {\n approvalTxId,\n },\n },\n };\n await handleApprovalDelay(quoteResponse.quote.srcChainId);\n }\n // Hardware-wallet delay first (Ledger second-prompt spacing), then wait for\n // on-chain approval confirmation so swap gas estimation runs after allowance is set.\n await handleMobileHardwareWalletDelay(requireApproval);\n if (requireApproval && approvalTxId) {\n await waitForTxConfirmation(args.messenger, approvalTxId);\n }\n\n const transactionType = isBridgeTx\n ? TransactionType.bridge\n : TransactionType.swap;\n\n let tradeMeta: TransactionMeta | undefined;\n try {\n tradeMeta = await handleSingleTx({\n ...args,\n transactionType,\n trade: quoteResponse.trade,\n // TODO figure out if this is needed\n // Pass txFee when gasIncluded is true to use the quote's gas fees\n // instead of re-estimating (which would fail for max native token swaps)\n txFee: quoteResponse.quote.gasIncluded\n ? quoteResponse.quote.feeData.txFee\n : undefined,\n actionId: tradeActionId,\n });\n } catch (error) {\n // Silence the error if tx has been added to the TransactionController to prevent duplicate Failed events\n tradeMeta = getTransactionMetaByActionId(args.messenger, tradeActionId);\n if (!tradeMeta) {\n throw error;\n }\n }\n\n yield {\n type: SubmitStep.SetTradeMeta,\n payload: { tradeMeta },\n };\n\n // Use the tradeMeta's id as history key\n yield {\n type: SubmitStep.RekeyHistoryItem,\n payload: {\n oldHistoryKey: tradeActionId,\n newHistoryKey: tradeMeta.id,\n tradeMeta,\n },\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"intent-strategy.d.ts","sourceRoot":"","sources":["../../src/strategy/intent-strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,MAAM,EACP,MAAM,6BAA6B,CAAC;AAgBrC,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAc,MAAM,YAAY,CAAC;AAsHhF;;;;;;;;;;;;GAYG;AACH,wBAAuB,mBAAmB,CACxC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,GACjC,cAAc,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,CAAC,CAoD9C"}
1
+ {"version":3,"file":"intent-strategy.d.ts","sourceRoot":"","sources":["../../src/strategy/intent-strategy.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,MAAM,EACP,MAAM,6BAA6B,CAAC;AAgBrC,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAc,MAAM,YAAY,CAAC;AAsHhF;;;;;;;;;;;;GAYG;AACH,wBAAuB,mBAAmB,CACxC,IAAI,EAAE,oBAAoB,CAAC,MAAM,CAAC,GACjC,cAAc,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,CAAC,CAqD9C"}
@@ -108,7 +108,8 @@ const handleSubmitIntent = async (args) => {
108
108
  */
109
109
  export async function* submitIntentHandler(args) {
110
110
  // TODO handle STX/batch approvals
111
- const approvalTxId = await handleEvmApprovals(args);
111
+ const approvalTxMeta = await handleEvmApprovals(args);
112
+ const approvalTxId = approvalTxMeta?.id;
112
113
  approvalTxId && (await waitForTxConfirmation(args.messenger, approvalTxId));
113
114
  // TODO add to history after approval tx is confirmed
114
115
  // Submit the intent order to the bridge-api
@@ -1 +1 @@
1
- {"version":3,"file":"intent-strategy.js","sourceRoot":"","sources":["../../src/strategy/intent-strategy.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/explicit-function-return-type */\nimport {\n formatChainIdToHex,\n isEvmTxData,\n TxData,\n} from '@metamask/bridge-controller';\nimport { TransactionType } from '@metamask/transaction-controller';\n\nimport { getJwt } from '../utils/authentication.js';\nimport {\n getIntentFromQuote,\n mapIntentOrderStatusToTransactionStatus,\n postSubmitOrder,\n} from '../utils/intent-api.js';\nimport { signTypedMessage } from '../utils/keyring.js';\nimport { getNetworkClientIdByChainId } from '../utils/network.js';\nimport {\n addSyntheticTransaction,\n waitForTxConfirmation,\n} from '../utils/transaction.js';\nimport { handleEvmApprovals } from './evm-strategy.js';\nimport { SubmitStrategyParams, SubmitStepResult, SubmitStep } from './types.js';\n\n/**\n * Submits a synthetic EVM transaction to the TransactionController in order to display the intent order's\n * status in theclients, before the actual transaction is finalized on chain. The resulting transaction\n * is only available locally and is not submitted to the chain.\n *\n * @param orderUid - The order uid of the intent transaction\n * @param args - The parameters for the transaction\n * @returns The tradeMeta for the synthetic transaction\n */\nconst handleSyntheticTx = async (\n orderUid: string,\n args: SubmitStrategyParams,\n) => {\n const {\n quoteResponses: [quoteResponse],\n messenger,\n isBridgeTx,\n selectedAccount,\n } = args;\n const {\n quote: { srcChainId },\n } = quoteResponse;\n\n // Determine transaction type: swap for same-chain, bridge for cross-chain\n const transactionType = isBridgeTx\n ? /* c8 ignore start */\n TransactionType.bridge\n : /* c8 ignore end */\n TransactionType.swap;\n\n const networkClientId = getNetworkClientIdByChainId(messenger, srcChainId);\n\n // This is a synthetic transaction whose purpose is to be able\n // to track the order status via the history\n if (!isEvmTxData(quoteResponse.trade)) {\n throw new Error('Failed to submit intent: trade is not an EVM transaction');\n }\n const intent = getIntentFromQuote(quoteResponse);\n // This is a synthetic transaction whose purpose is to be able\n // to track the order status via the history\n /**\n * @deprecated use trade data from quote response instead\n */\n const intentTransactionParams = {\n chainId: formatChainIdToHex(srcChainId),\n from: selectedAccount.address,\n to:\n intent.settlementContract ?? '0x9008D19f58AAbd9eD0D60971565AA8510560ab41', // Default settlement contract\n data: `0x${orderUid?.slice(-8)}`, // Use last 8 chars of orderUid to make each transaction unique\n value: '0x0',\n gas: '0x5208', // Minimal gas for display purposes\n gasPrice: '0x3b9aca00', // 1 Gwei - will be converted to EIP-1559 fees if network supports it\n };\n\n const initialTxMeta = await addSyntheticTransaction(\n messenger,\n intentTransactionParams,\n {\n requireApproval: false,\n networkClientId,\n type: transactionType,\n },\n );\n return initialTxMeta;\n};\n\n/**\n * Submits batched EVM transactions to the TransactionController\n *\n * @param args - The parameters for the transaction\n * @param args.quoteResponse - The quote response\n * @param args.messenger - The messenger\n * @param args.selectedAccount - The selected account\n * @param args.traceFn - The trace function\n * @param args.isBridgeTx - Whether the transaction is a bridge transaction\n * @returns The approvalTxId and tradeMeta for the non-EVM transaction\n */\nconst handleSubmitIntent = async (args: SubmitStrategyParams<TxData>) => {\n const {\n quoteResponses: [quoteResponse],\n messenger,\n selectedAccount,\n clientId,\n fetchFn,\n bridgeApiBaseUrl,\n } = args;\n const { srcChainId, requestId } = quoteResponse.quote;\n\n const intent = getIntentFromQuote(quoteResponse);\n const signature = await signTypedMessage({\n messenger,\n accountAddress: selectedAccount.address,\n typedData: intent.typedData,\n });\n\n const { id: orderUid, status } = await postSubmitOrder({\n params: {\n srcChainId,\n quoteId: requestId,\n signature,\n order: intent.order,\n userAddress: selectedAccount.address,\n aggregatorId: intent.protocol,\n },\n clientId,\n jwt: await getJwt(messenger),\n fetchFn,\n bridgeApiBaseUrl,\n });\n\n return {\n orderUid,\n orderStatus: status,\n };\n};\n\n/**\n * Submits an approval tx to the TransactionController,\n * posts an intent order to the bridge-api,\n * and creates a synthetic transaction in the TransactionController\n *\n * @param args - The parameters for the transaction\n * @param args.quoteResponse - The quote response\n * @param args.messenger - The messenger\n * @param args.selectedAccount - The selected account\n * @param args.traceFn - The trace function\n * @param args.isBridgeTx - Whether the transaction is a bridge transaction\n * @yields The approvalTxId and tradeMeta for the intent transaction\n */\nexport async function* submitIntentHandler(\n args: SubmitStrategyParams<TxData>,\n): AsyncGenerator<SubmitStepResult, void, void> {\n // TODO handle STX/batch approvals\n const approvalTxId = await handleEvmApprovals(args);\n approvalTxId && (await waitForTxConfirmation(args.messenger, approvalTxId));\n\n // TODO add to history after approval tx is confirmed\n\n // Submit the intent order to the bridge-api\n const { orderUid, orderStatus } = await handleSubmitIntent(args);\n\n // Initialize a transaction in the TransactionController\n const syntheticTxMeta = await handleSyntheticTx(orderUid, {\n ...args,\n requireApproval: false,\n isStxEnabled: false,\n });\n\n // Use synthetic transaction metadata + translated intent order status as the tradeMeta\n yield {\n type: SubmitStep.SetTradeMeta,\n payload: {\n tradeMeta: {\n ...syntheticTxMeta,\n // Map intent order status to TransactionController status\n status: mapIntentOrderStatusToTransactionStatus(orderStatus),\n },\n },\n };\n\n // Update txHistory with synthetic txMeta and order id\n yield {\n type: SubmitStep.AddHistoryItem,\n payload: {\n // Use orderId as the history key for intent transactions\n historyKey: orderUid,\n bridgeTxMeta: {\n id: syntheticTxMeta?.id,\n },\n approvalTxId,\n // Keep original txId for TransactionController updates\n originalTransactionId: syntheticTxMeta?.id,\n quoteResponse: args.quoteResponses[0],\n },\n };\n\n // Start polling using the orderId as the history key\n yield {\n type: SubmitStep.StartPolling,\n payload: {\n historyKey: orderUid,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"intent-strategy.js","sourceRoot":"","sources":["../../src/strategy/intent-strategy.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/explicit-function-return-type */\nimport {\n formatChainIdToHex,\n isEvmTxData,\n TxData,\n} from '@metamask/bridge-controller';\nimport { TransactionType } from '@metamask/transaction-controller';\n\nimport { getJwt } from '../utils/authentication.js';\nimport {\n getIntentFromQuote,\n mapIntentOrderStatusToTransactionStatus,\n postSubmitOrder,\n} from '../utils/intent-api.js';\nimport { signTypedMessage } from '../utils/keyring.js';\nimport { getNetworkClientIdByChainId } from '../utils/network.js';\nimport {\n addSyntheticTransaction,\n waitForTxConfirmation,\n} from '../utils/transaction.js';\nimport { handleEvmApprovals } from './evm-strategy.js';\nimport { SubmitStrategyParams, SubmitStepResult, SubmitStep } from './types.js';\n\n/**\n * Submits a synthetic EVM transaction to the TransactionController in order to display the intent order's\n * status in theclients, before the actual transaction is finalized on chain. The resulting transaction\n * is only available locally and is not submitted to the chain.\n *\n * @param orderUid - The order uid of the intent transaction\n * @param args - The parameters for the transaction\n * @returns The tradeMeta for the synthetic transaction\n */\nconst handleSyntheticTx = async (\n orderUid: string,\n args: SubmitStrategyParams,\n) => {\n const {\n quoteResponses: [quoteResponse],\n messenger,\n isBridgeTx,\n selectedAccount,\n } = args;\n const {\n quote: { srcChainId },\n } = quoteResponse;\n\n // Determine transaction type: swap for same-chain, bridge for cross-chain\n const transactionType = isBridgeTx\n ? /* c8 ignore start */\n TransactionType.bridge\n : /* c8 ignore end */\n TransactionType.swap;\n\n const networkClientId = getNetworkClientIdByChainId(messenger, srcChainId);\n\n // This is a synthetic transaction whose purpose is to be able\n // to track the order status via the history\n if (!isEvmTxData(quoteResponse.trade)) {\n throw new Error('Failed to submit intent: trade is not an EVM transaction');\n }\n const intent = getIntentFromQuote(quoteResponse);\n // This is a synthetic transaction whose purpose is to be able\n // to track the order status via the history\n /**\n * @deprecated use trade data from quote response instead\n */\n const intentTransactionParams = {\n chainId: formatChainIdToHex(srcChainId),\n from: selectedAccount.address,\n to:\n intent.settlementContract ?? '0x9008D19f58AAbd9eD0D60971565AA8510560ab41', // Default settlement contract\n data: `0x${orderUid?.slice(-8)}`, // Use last 8 chars of orderUid to make each transaction unique\n value: '0x0',\n gas: '0x5208', // Minimal gas for display purposes\n gasPrice: '0x3b9aca00', // 1 Gwei - will be converted to EIP-1559 fees if network supports it\n };\n\n const initialTxMeta = await addSyntheticTransaction(\n messenger,\n intentTransactionParams,\n {\n requireApproval: false,\n networkClientId,\n type: transactionType,\n },\n );\n return initialTxMeta;\n};\n\n/**\n * Submits batched EVM transactions to the TransactionController\n *\n * @param args - The parameters for the transaction\n * @param args.quoteResponse - The quote response\n * @param args.messenger - The messenger\n * @param args.selectedAccount - The selected account\n * @param args.traceFn - The trace function\n * @param args.isBridgeTx - Whether the transaction is a bridge transaction\n * @returns The approvalTxId and tradeMeta for the non-EVM transaction\n */\nconst handleSubmitIntent = async (args: SubmitStrategyParams<TxData>) => {\n const {\n quoteResponses: [quoteResponse],\n messenger,\n selectedAccount,\n clientId,\n fetchFn,\n bridgeApiBaseUrl,\n } = args;\n const { srcChainId, requestId } = quoteResponse.quote;\n\n const intent = getIntentFromQuote(quoteResponse);\n const signature = await signTypedMessage({\n messenger,\n accountAddress: selectedAccount.address,\n typedData: intent.typedData,\n });\n\n const { id: orderUid, status } = await postSubmitOrder({\n params: {\n srcChainId,\n quoteId: requestId,\n signature,\n order: intent.order,\n userAddress: selectedAccount.address,\n aggregatorId: intent.protocol,\n },\n clientId,\n jwt: await getJwt(messenger),\n fetchFn,\n bridgeApiBaseUrl,\n });\n\n return {\n orderUid,\n orderStatus: status,\n };\n};\n\n/**\n * Submits an approval tx to the TransactionController,\n * posts an intent order to the bridge-api,\n * and creates a synthetic transaction in the TransactionController\n *\n * @param args - The parameters for the transaction\n * @param args.quoteResponse - The quote response\n * @param args.messenger - The messenger\n * @param args.selectedAccount - The selected account\n * @param args.traceFn - The trace function\n * @param args.isBridgeTx - Whether the transaction is a bridge transaction\n * @yields The approvalTxId and tradeMeta for the intent transaction\n */\nexport async function* submitIntentHandler(\n args: SubmitStrategyParams<TxData>,\n): AsyncGenerator<SubmitStepResult, void, void> {\n // TODO handle STX/batch approvals\n const approvalTxMeta = await handleEvmApprovals(args);\n const approvalTxId = approvalTxMeta?.id;\n approvalTxId && (await waitForTxConfirmation(args.messenger, approvalTxId));\n\n // TODO add to history after approval tx is confirmed\n\n // Submit the intent order to the bridge-api\n const { orderUid, orderStatus } = await handleSubmitIntent(args);\n\n // Initialize a transaction in the TransactionController\n const syntheticTxMeta = await handleSyntheticTx(orderUid, {\n ...args,\n requireApproval: false,\n isStxEnabled: false,\n });\n\n // Use synthetic transaction metadata + translated intent order status as the tradeMeta\n yield {\n type: SubmitStep.SetTradeMeta,\n payload: {\n tradeMeta: {\n ...syntheticTxMeta,\n // Map intent order status to TransactionController status\n status: mapIntentOrderStatusToTransactionStatus(orderStatus),\n },\n },\n };\n\n // Update txHistory with synthetic txMeta and order id\n yield {\n type: SubmitStep.AddHistoryItem,\n payload: {\n // Use orderId as the history key for intent transactions\n historyKey: orderUid,\n bridgeTxMeta: {\n id: syntheticTxMeta?.id,\n },\n approvalTxId,\n // Keep original txId for TransactionController updates\n originalTransactionId: syntheticTxMeta?.id,\n quoteResponse: args.quoteResponses[0],\n },\n };\n\n // Start polling using the orderId as the history key\n yield {\n type: SubmitStep.StartPolling,\n payload: {\n historyKey: orderUid,\n },\n };\n}\n"]}