@@ -18,6 +18,8 @@ import {
1818} from "../types/index.js" ;
1919import { parseFillLogs , waitForFillTx } from "./waitForFillTx.js" ;
2020import { parseDepositLogs } from "./getDepositFromLogs.js" ;
21+ import { prepareAtomicApproveDepositTx } from "./prepareAtomicApproveDepositTx.js" ;
22+ import { waitForAtomicTx } from "./waitForAtomicTx.js" ;
2123
2224export type ExecutionProgress = TransactionProgress ;
2325
@@ -161,6 +163,10 @@ export type ExecuteQuoteParams = {
161163 * The logger to use.
162164 */
163165 logger ?: LoggerT ;
166+ /**
167+ * Whether to use atomic transactions if supported by the wallet.
168+ */
169+ atomicIfSupported ?: boolean ;
164170} ;
165171
166172/**
@@ -194,7 +200,9 @@ export type ExecuteQuoteResponseParams = {
194200 * @returns The deposit ID and receipts for the deposit and fill transactions. See {@link ExecuteQuoteResponseParams}.
195201 * @public
196202 */
197- export async function executeQuote ( params : ExecuteQuoteParams ) : Promise < ExecuteQuoteResponseParams > {
203+ export async function executeQuote (
204+ params : ExecuteQuoteParams ,
205+ ) : Promise < ExecuteQuoteResponseParams > {
198206 const {
199207 integratorId,
200208 deposit,
@@ -207,6 +215,7 @@ export async function executeQuote(params: ExecuteQuoteParams): Promise<ExecuteQ
207215 forceOriginChain,
208216 onProgress,
209217 logger,
218+ atomicIfSupported = false ,
210219 } = params ;
211220
212221 const onProgressHandler =
@@ -281,6 +290,111 @@ export async function executeQuote(params: ExecuteQuoteParams): Promise<ExecuteQ
281290
282291 onProgressHandler ( currentTransactionProgress ) ;
283292
293+ if ( atomicIfSupported ) {
294+ logger ?. debug ( "Checking if wallet supports atomic transactions" ) ;
295+ try {
296+ const capabilities = await walletClient . getCapabilities ( {
297+ account,
298+ chainId : deposit . originChainId ,
299+ } ) ;
300+
301+ if (
302+ capabilities ?. atomic ?. status === "supported" ||
303+ capabilities ?. atomic ?. status === "ready"
304+ ) {
305+ logger ?. debug (
306+ "Wallet supports atomic sendCalls, triggering atomic flow" ,
307+ ) ;
308+ // Simulate both approval and deposit calls
309+ const { calls } = await prepareAtomicApproveDepositTx ( {
310+ walletClient,
311+ publicClient : originClient ,
312+ deposit,
313+ approvalAmount : BigInt ( inputAmount ) ,
314+ integratorId,
315+ logger,
316+ } ) ;
317+
318+ const { id : callId } = await walletClient . sendCalls ( {
319+ account,
320+ calls,
321+ forceAtomic : true ,
322+ } ) ;
323+
324+ logger ?. debug ( `Atomic call ID: ${ callId } ` ) ;
325+
326+ const destinationBlock = await destinationClient . getBlockNumber ( ) ;
327+
328+ const { depositId, depositTxReceipt } = await waitForAtomicTx ( {
329+ callId,
330+ originChainId : deposit . originChainId ,
331+ walletClient,
332+ } ) ;
333+
334+ const depositLog = parseDepositLogs ( depositTxReceipt . logs ) ;
335+
336+ const depositSuccessProgress : TransactionProgress = {
337+ step : "deposit" ,
338+ status : "txSuccess" ,
339+ txReceipt : depositTxReceipt ,
340+ depositId,
341+ depositLog,
342+ meta : { deposit } ,
343+ } ;
344+ onProgressHandler ( depositSuccessProgress ) ;
345+
346+ // After successful deposit, wait for fill
347+ const fillMeta : FillMeta = {
348+ depositId,
349+ deposit,
350+ } ;
351+ const fillPendingProgress : TransactionProgress = {
352+ step : "fill" ,
353+ status : "txPending" ,
354+ meta : fillMeta ,
355+ } ;
356+ onProgressHandler ( fillPendingProgress ) ;
357+
358+ const { fillTxReceipt, fillTxTimestamp, actionSuccess } =
359+ await waitForFillTx ( {
360+ deposit,
361+ depositId,
362+ depositTxHash : depositTxReceipt . transactionHash ,
363+ destinationChainClient : destinationClient ,
364+ fromBlock : destinationBlock - 100n , // TODO: use dynamic block buffer based chain
365+ } ) ;
366+
367+ const fillLog = parseFillLogs ( fillTxReceipt . logs ) ;
368+
369+ const fillSuccessProgress : TransactionProgress = {
370+ step : "fill" ,
371+ status : "txSuccess" ,
372+ txReceipt : fillTxReceipt ,
373+ fillTxTimestamp,
374+ actionSuccess,
375+ fillLog,
376+ meta : fillMeta ,
377+ } ;
378+ onProgressHandler ( fillSuccessProgress ) ;
379+ return { depositId, depositTxReceipt, fillTxReceipt } ;
380+ }
381+ } catch ( error ) {
382+ if (
383+ error instanceof Error &&
384+ error . message
385+ . toLowerCase ( )
386+ . includes ( "user rejected account upgrade" )
387+ ) {
388+ logger ?. debug (
389+ "User rejected smart account upgrade, falling back to regular flow" ,
390+ ) ;
391+ } else {
392+ throw error ;
393+ }
394+ }
395+ }
396+
397+ // Fall back to regular approval flow
284398 const { request } = await simulateApproveTx ( {
285399 walletClient,
286400 publicClient : originClient ,
0 commit comments