@lifi/sdk 3.6.0-beta.3 → 3.6.0-beta.4

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 (96) hide show
  1. package/package.json +4 -4
  2. package/src/_cjs/core/EVM/EVMStepExecutor.js +250 -220
  3. package/src/_cjs/core/EVM/EVMStepExecutor.js.map +1 -1
  4. package/src/_cjs/core/EVM/parseEVMErrors.js +2 -1
  5. package/src/_cjs/core/EVM/parseEVMErrors.js.map +1 -1
  6. package/src/_cjs/core/EVM/typeguards.js +2 -2
  7. package/src/_cjs/core/EVM/typeguards.js.map +1 -1
  8. package/src/_cjs/core/Solana/SolanaStepExecutor.js +1 -13
  9. package/src/_cjs/core/Solana/SolanaStepExecutor.js.map +1 -1
  10. package/src/_cjs/core/Solana/parseSolanaErrors.js.map +1 -1
  11. package/src/_cjs/core/StatusManager.js +13 -9
  12. package/src/_cjs/core/StatusManager.js.map +1 -1
  13. package/src/_cjs/core/UTXO/UTXOStepExecutor.js +1 -13
  14. package/src/_cjs/core/UTXO/UTXOStepExecutor.js.map +1 -1
  15. package/src/_cjs/core/UTXO/parseUTXOErrors.js.map +1 -1
  16. package/src/_cjs/core/processMessages.js +22 -15
  17. package/src/_cjs/core/processMessages.js.map +1 -1
  18. package/src/_cjs/core/waitForDestinationChainTransaction.js +16 -1
  19. package/src/_cjs/core/waitForDestinationChainTransaction.js.map +1 -1
  20. package/src/_cjs/core/waitForTransactionStatus.js.map +1 -1
  21. package/src/_cjs/errors/SDKError.js.map +1 -1
  22. package/src/_cjs/index.js +2 -2
  23. package/src/_cjs/index.js.map +1 -1
  24. package/src/_cjs/utils/getTransactionMessage.js.map +1 -1
  25. package/src/_cjs/version.js +1 -1
  26. package/src/_esm/core/EVM/EVMStepExecutor.js +273 -242
  27. package/src/_esm/core/EVM/EVMStepExecutor.js.map +1 -1
  28. package/src/_esm/core/EVM/parseEVMErrors.js +2 -1
  29. package/src/_esm/core/EVM/parseEVMErrors.js.map +1 -1
  30. package/src/_esm/core/EVM/typeguards.js +1 -1
  31. package/src/_esm/core/EVM/typeguards.js.map +1 -1
  32. package/src/_esm/core/Solana/SolanaStepExecutor.js +1 -14
  33. package/src/_esm/core/Solana/SolanaStepExecutor.js.map +1 -1
  34. package/src/_esm/core/Solana/parseSolanaErrors.js.map +1 -1
  35. package/src/_esm/core/StatusManager.js +24 -18
  36. package/src/_esm/core/StatusManager.js.map +1 -1
  37. package/src/_esm/core/UTXO/UTXOStepExecutor.js +1 -14
  38. package/src/_esm/core/UTXO/UTXOStepExecutor.js.map +1 -1
  39. package/src/_esm/core/UTXO/parseUTXOErrors.js.map +1 -1
  40. package/src/_esm/core/processMessages.js +22 -15
  41. package/src/_esm/core/processMessages.js.map +1 -1
  42. package/src/_esm/core/waitForDestinationChainTransaction.js +17 -1
  43. package/src/_esm/core/waitForDestinationChainTransaction.js.map +1 -1
  44. package/src/_esm/core/waitForTransactionStatus.js.map +1 -1
  45. package/src/_esm/errors/SDKError.js.map +1 -1
  46. package/src/_esm/index.js +1 -1
  47. package/src/_esm/index.js.map +1 -1
  48. package/src/_esm/utils/getTransactionMessage.js.map +1 -1
  49. package/src/_esm/version.js +1 -1
  50. package/src/_types/core/EVM/EVMStepExecutor.d.ts +13 -3
  51. package/src/_types/core/EVM/EVMStepExecutor.d.ts.map +1 -1
  52. package/src/_types/core/EVM/checkAllowance.d.ts.map +1 -1
  53. package/src/_types/core/EVM/parseEVMErrors.d.ts +2 -1
  54. package/src/_types/core/EVM/parseEVMErrors.d.ts.map +1 -1
  55. package/src/_types/core/EVM/typeguards.d.ts +1 -1
  56. package/src/_types/core/EVM/typeguards.d.ts.map +1 -1
  57. package/src/_types/core/Solana/SolanaStepExecutor.d.ts.map +1 -1
  58. package/src/_types/core/Solana/parseSolanaErrors.d.ts +2 -1
  59. package/src/_types/core/Solana/parseSolanaErrors.d.ts.map +1 -1
  60. package/src/_types/core/StatusManager.d.ts +14 -11
  61. package/src/_types/core/StatusManager.d.ts.map +1 -1
  62. package/src/_types/core/UTXO/UTXOStepExecutor.d.ts.map +1 -1
  63. package/src/_types/core/UTXO/parseUTXOErrors.d.ts +2 -1
  64. package/src/_types/core/UTXO/parseUTXOErrors.d.ts.map +1 -1
  65. package/src/_types/core/processMessages.d.ts +3 -1
  66. package/src/_types/core/processMessages.d.ts.map +1 -1
  67. package/src/_types/core/types.d.ts +32 -1
  68. package/src/_types/core/types.d.ts.map +1 -1
  69. package/src/_types/core/waitForDestinationChainTransaction.d.ts +3 -3
  70. package/src/_types/core/waitForDestinationChainTransaction.d.ts.map +1 -1
  71. package/src/_types/core/waitForTransactionStatus.d.ts +2 -1
  72. package/src/_types/core/waitForTransactionStatus.d.ts.map +1 -1
  73. package/src/_types/errors/SDKError.d.ts +2 -1
  74. package/src/_types/errors/SDKError.d.ts.map +1 -1
  75. package/src/_types/index.d.ts +2 -2
  76. package/src/_types/index.d.ts.map +1 -1
  77. package/src/_types/utils/getTransactionMessage.d.ts +2 -1
  78. package/src/_types/utils/getTransactionMessage.d.ts.map +1 -1
  79. package/src/_types/version.d.ts +1 -1
  80. package/src/core/EVM/EVMStepExecutor.ts +352 -301
  81. package/src/core/EVM/checkAllowance.ts +2 -2
  82. package/src/core/EVM/parseEVMErrors.ts +6 -2
  83. package/src/core/EVM/typeguards.ts +1 -1
  84. package/src/core/Solana/SolanaStepExecutor.ts +2 -16
  85. package/src/core/Solana/parseSolanaErrors.ts +2 -1
  86. package/src/core/StatusManager.ts +38 -26
  87. package/src/core/UTXO/UTXOStepExecutor.ts +2 -16
  88. package/src/core/UTXO/parseUTXOErrors.ts +2 -1
  89. package/src/core/processMessages.ts +25 -21
  90. package/src/core/types.ts +54 -1
  91. package/src/core/waitForDestinationChainTransaction.ts +21 -4
  92. package/src/core/waitForTransactionStatus.ts +2 -6
  93. package/src/errors/SDKError.ts +2 -1
  94. package/src/index.ts +6 -1
  95. package/src/utils/getTransactionMessage.ts +2 -1
  96. package/src/version.ts +1 -1
@@ -1,4 +1,4 @@
1
- import type { LiFiStep, Process } from '@lifi/types'
1
+ import type { ExtendedChain, LiFiStep } from '@lifi/types'
2
2
  import type {
3
3
  Address,
4
4
  Client,
@@ -20,12 +20,12 @@ import {
20
20
  getStepTransaction,
21
21
  relayTransaction,
22
22
  } from '../../services/api.js'
23
- import { isZeroAddress } from '../../utils/isZeroAddress.js'
24
23
  import { BaseStepExecutor } from '../BaseStepExecutor.js'
25
24
  import { checkBalance } from '../checkBalance.js'
26
25
  import { stepComparison } from '../stepComparison.js'
27
26
  import type {
28
27
  LiFiStepExtended,
28
+ Process,
29
29
  StepExecutorOptions,
30
30
  TransactionParameters,
31
31
  } from '../types.js'
@@ -35,7 +35,7 @@ import { getNativePermit } from './getNativePermit.js'
35
35
  import { parseEVMErrors } from './parseEVMErrors.js'
36
36
  import { type PermitSignature, signPermitMessage } from './signPermitMessage.js'
37
37
  import { switchChain } from './switchChain.js'
38
- import { isEVMPermitStep } from './typeguards.js'
38
+ import { isRelayerStep } from './typeguards.js'
39
39
  import { getMaxPriorityFeePerGas } from './utils.js'
40
40
  import {
41
41
  type WalletCallReceipt,
@@ -116,6 +116,78 @@ export class EVMStepExecutor extends BaseStepExecutor {
116
116
  return updatedClient
117
117
  }
118
118
 
119
+ waitForTransaction = async ({
120
+ step,
121
+ process,
122
+ fromChain,
123
+ toChain,
124
+ atomicBatchSupported,
125
+ isRelayerTransaction,
126
+ txHash,
127
+ isBridgeExecution,
128
+ }: {
129
+ step: LiFiStepExtended
130
+ process: Process
131
+ fromChain: ExtendedChain
132
+ toChain: ExtendedChain
133
+ atomicBatchSupported: boolean
134
+ isRelayerTransaction: boolean
135
+ txHash: Hash
136
+ isBridgeExecution: boolean
137
+ }) => {
138
+ let transactionReceipt: TransactionReceipt | WalletCallReceipt | undefined
139
+
140
+ if (atomicBatchSupported) {
141
+ transactionReceipt = await waitForBatchTransactionReceipt(
142
+ this.client,
143
+ txHash
144
+ )
145
+ } else if (isRelayerTransaction) {
146
+ transactionReceipt = await waitForRelayedTransactionReceipt(txHash)
147
+ } else {
148
+ transactionReceipt = await waitForTransactionReceipt({
149
+ client: this.client,
150
+ chainId: fromChain.id,
151
+ txHash,
152
+ onReplaced: (response) => {
153
+ this.statusManager.updateProcess(step, process.type, 'PENDING', {
154
+ txHash: response.transaction.hash,
155
+ txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
156
+ })
157
+ },
158
+ })
159
+ }
160
+
161
+ // Update pending process if the transaction hash from the receipt is different.
162
+ // This might happen if the transaction was replaced.
163
+ if (
164
+ transactionReceipt?.transactionHash &&
165
+ transactionReceipt.transactionHash !== txHash
166
+ ) {
167
+ process = this.statusManager.updateProcess(
168
+ step,
169
+ process.type,
170
+ 'PENDING',
171
+ {
172
+ txHash: transactionReceipt.transactionHash,
173
+ txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${transactionReceipt.transactionHash}`,
174
+ }
175
+ )
176
+ }
177
+
178
+ if (isBridgeExecution) {
179
+ process = this.statusManager.updateProcess(step, process.type, 'DONE')
180
+ }
181
+
182
+ await waitForDestinationChainTransaction(
183
+ step,
184
+ process,
185
+ fromChain,
186
+ toChain,
187
+ this.statusManager
188
+ )
189
+ }
190
+
119
191
  executeStep = async (step: LiFiStepExtended): Promise<LiFiStepExtended> => {
120
192
  step.execution = this.statusManager.initExecutionObject(step)
121
193
 
@@ -138,6 +210,8 @@ export class EVMStepExecutor extends BaseStepExecutor {
138
210
  const fromChain = await config.getChainById(step.action.fromChainId)
139
211
  const toChain = await config.getChainById(step.action.toChainId)
140
212
 
213
+ // Check if the wallet supports atomic batch transactions (EIP-5792)
214
+ const calls: Call[] = []
141
215
  let atomicBatchSupported = false
142
216
  try {
143
217
  const capabilities = (await getAction(
@@ -147,11 +221,10 @@ export class EVMStepExecutor extends BaseStepExecutor {
147
221
  )(undefined)) as GetCapabilitiesReturnType
148
222
  atomicBatchSupported = capabilities[fromChain.id]?.atomicBatch?.supported
149
223
  } catch {
150
- // If the wallet does not support getCapabilities, we assume that atomic batch is not supported
224
+ // If the wallet does not support getCapabilities or the call fails,
225
+ // we assume that atomic batch is not supported
151
226
  }
152
227
 
153
- const calls: Call[] = []
154
-
155
228
  const isBridgeExecution = fromChain.id !== toChain.id
156
229
  const currentProcessType = isBridgeExecution ? 'CROSS_CHAIN' : 'SWAP'
157
230
 
@@ -160,8 +233,11 @@ export class EVMStepExecutor extends BaseStepExecutor {
160
233
  (p) => p.type === currentProcessType
161
234
  )
162
235
 
236
+ const isFromNativeToken =
237
+ fromChain.nativeToken.address === step.action.fromToken.address
238
+
163
239
  // Check if step requires permit signature and will be used with relayer service
164
- const isPermitStep = isEVMPermitStep(step)
240
+ const isRelayerTransaction = isRelayerStep(step)
165
241
 
166
242
  // Check if token requires approval
167
243
  // Native tokens (like ETH) don't need approval since they're not ERC20 tokens
@@ -176,13 +252,17 @@ export class EVMStepExecutor extends BaseStepExecutor {
176
252
  )
177
253
  // Check if proxy contract is available and token supports native permits, not available for atomic batch
178
254
  const nativePermitSupported =
179
- !!fromChain.permit2Proxy &&
180
255
  nativePermit.supported &&
256
+ !!fromChain.permit2Proxy &&
181
257
  !atomicBatchSupported &&
182
- !isPermitStep
258
+ !isRelayerTransaction && // TODO: remove once we support ERC-2771
259
+ !isFromNativeToken
183
260
  // Check if chain has Permit2 contract deployed. Permit2 should not be available for atomic batch.
184
261
  const permit2Supported =
185
- !!fromChain.permit2 && !!fromChain.permit2Proxy && !atomicBatchSupported
262
+ !!fromChain.permit2 &&
263
+ !!fromChain.permit2Proxy &&
264
+ !atomicBatchSupported &&
265
+ !isFromNativeToken
186
266
  // Token supports either native permits or Permit2
187
267
  const permitSupported = permit2Supported || nativePermitSupported
188
268
 
@@ -190,7 +270,7 @@ export class EVMStepExecutor extends BaseStepExecutor {
190
270
  // No existing swap/bridgetransaction is pending
191
271
  !existingProcess?.txHash &&
192
272
  // Token is not native (address is not zero)
193
- !isZeroAddress(step.action.fromToken.address) &&
273
+ !isFromNativeToken &&
194
274
  // Token doesn't support native permits
195
275
  !nativePermitSupported
196
276
 
@@ -220,325 +300,296 @@ export class EVMStepExecutor extends BaseStepExecutor {
220
300
  }
221
301
  }
222
302
 
223
- let process = this.statusManager.findOrCreateProcess({
224
- step,
225
- type: currentProcessType,
226
- chainId: fromChain.id,
227
- })
228
-
229
- if (process.status !== 'DONE') {
230
- try {
231
- let txHash: Hash
232
- if (process.txHash) {
233
- // Make sure that the chain is still correct
234
- const updatedClient = await this.checkClient(step, process)
235
- if (!updatedClient) {
236
- return step
237
- }
303
+ let process = this.statusManager.findProcess(step, currentProcessType)
238
304
 
239
- // Wait for exiting transaction
240
- txHash = process.txHash as Hash
241
- } else {
242
- process = this.statusManager.updateProcess(
243
- step,
244
- process.type,
245
- 'STARTED'
246
- )
305
+ if (process?.status === 'DONE') {
306
+ await waitForDestinationChainTransaction(
307
+ step,
308
+ process,
309
+ fromChain,
310
+ toChain,
311
+ this.statusManager
312
+ )
247
313
 
248
- // Check balance
249
- await checkBalance(this.client.account!.address, step)
250
-
251
- // Create new transaction request
252
- if (!step.transactionRequest) {
253
- const { execution, ...stepBase } = step
254
- let updatedStep: LiFiStep
255
- if (isPermitStep) {
256
- const updatedRelayedStep = await getRelayerQuote({
257
- fromChain: stepBase.action.fromChainId,
258
- fromToken: stepBase.action.fromToken.address,
259
- fromAddress: stepBase.action.fromAddress!,
260
- fromAmount: stepBase.action.fromAmount,
261
- toChain: stepBase.action.toChainId,
262
- toToken: stepBase.action.toToken.address,
263
- slippage: stepBase.action.slippage,
264
- toAddress: stepBase.action.toAddress,
265
- allowBridges: [stepBase.tool],
266
- })
267
- updatedStep = {
268
- ...updatedRelayedStep.data.quote.step,
269
- ...updatedRelayedStep.data.quote,
270
- id: stepBase.id,
271
- }
272
- } else {
273
- updatedStep = await getStepTransaction(stepBase)
274
- }
275
- const comparedStep = await stepComparison(
276
- this.statusManager,
277
- step,
278
- updatedStep,
279
- this.allowUserInteraction,
280
- this.executionOptions
281
- )
282
- Object.assign(step, {
283
- ...comparedStep,
284
- execution: step.execution,
285
- })
286
- }
314
+ return step
315
+ }
287
316
 
288
- if (!step.transactionRequest) {
289
- throw new TransactionError(
290
- LiFiErrorCode.TransactionUnprepared,
291
- 'Unable to prepare transaction.'
292
- )
317
+ try {
318
+ if (process?.txHash) {
319
+ // Make sure that the chain is still correct
320
+ const updatedClient = await this.checkClient(step, process)
321
+ if (!updatedClient) {
322
+ return step
323
+ }
324
+
325
+ // Wait for exiting transaction
326
+ const txHash = process.txHash as Hash
327
+
328
+ await this.waitForTransaction({
329
+ step,
330
+ process,
331
+ fromChain,
332
+ toChain,
333
+ atomicBatchSupported,
334
+ isRelayerTransaction,
335
+ txHash,
336
+ isBridgeExecution,
337
+ })
338
+
339
+ return step
340
+ }
341
+
342
+ process = this.statusManager.findOrCreateProcess({
343
+ step,
344
+ type: permitSupported ? 'PERMIT' : currentProcessType,
345
+ status: 'STARTED',
346
+ })
347
+
348
+ // Check balance
349
+ await checkBalance(this.client.account!.address, step)
350
+
351
+ // Create new transaction request
352
+ if (!step.transactionRequest) {
353
+ const { execution, ...stepBase } = step
354
+ let updatedStep: LiFiStep
355
+ if (isRelayerTransaction) {
356
+ const updatedRelayedStep = await getRelayerQuote({
357
+ fromChain: stepBase.action.fromChainId,
358
+ fromToken: stepBase.action.fromToken.address,
359
+ fromAddress: stepBase.action.fromAddress!,
360
+ fromAmount: stepBase.action.fromAmount,
361
+ toChain: stepBase.action.toChainId,
362
+ toToken: stepBase.action.toToken.address,
363
+ slippage: stepBase.action.slippage,
364
+ toAddress: stepBase.action.toAddress,
365
+ allowBridges: [stepBase.tool],
366
+ })
367
+ updatedStep = {
368
+ ...updatedRelayedStep.data.quote.step,
369
+ ...updatedRelayedStep.data.quote,
370
+ id: stepBase.id,
293
371
  }
372
+ } else {
373
+ updatedStep = await getStepTransaction(stepBase)
374
+ }
375
+ const comparedStep = await stepComparison(
376
+ this.statusManager,
377
+ step,
378
+ updatedStep,
379
+ this.allowUserInteraction,
380
+ this.executionOptions
381
+ )
382
+ Object.assign(step, {
383
+ ...comparedStep,
384
+ execution: step.execution,
385
+ })
386
+ }
294
387
 
295
- let transactionRequest: TransactionParameters = {
296
- to: step.transactionRequest.to,
297
- from: step.transactionRequest.from,
298
- data: step.transactionRequest.data,
299
- value: step.transactionRequest.value
300
- ? BigInt(step.transactionRequest.value)
301
- : undefined,
302
- gas: step.transactionRequest.gasLimit
303
- ? BigInt(step.transactionRequest.gasLimit)
388
+ if (!step.transactionRequest) {
389
+ throw new TransactionError(
390
+ LiFiErrorCode.TransactionUnprepared,
391
+ 'Unable to prepare transaction.'
392
+ )
393
+ }
394
+
395
+ let transactionRequest: TransactionParameters = {
396
+ to: step.transactionRequest.to,
397
+ from: step.transactionRequest.from,
398
+ data: step.transactionRequest.data,
399
+ value: step.transactionRequest.value
400
+ ? BigInt(step.transactionRequest.value)
401
+ : undefined,
402
+ gas: step.transactionRequest.gasLimit
403
+ ? BigInt(step.transactionRequest.gasLimit)
404
+ : undefined,
405
+ // gasPrice: step.transactionRequest.gasPrice
406
+ // ? BigInt(step.transactionRequest.gasPrice as string)
407
+ // : undefined,
408
+ // maxFeePerGas: step.transactionRequest.maxFeePerGas
409
+ // ? BigInt(step.transactionRequest.maxFeePerGas as string)
410
+ // : undefined,
411
+ maxPriorityFeePerGas:
412
+ this.client.account?.type === 'local'
413
+ ? await getMaxPriorityFeePerGas(this.client)
414
+ : step.transactionRequest.maxPriorityFeePerGas
415
+ ? BigInt(step.transactionRequest.maxPriorityFeePerGas)
304
416
  : undefined,
305
- // gasPrice: step.transactionRequest.gasPrice
306
- // ? BigInt(step.transactionRequest.gasPrice as string)
307
- // : undefined,
308
- // maxFeePerGas: step.transactionRequest.maxFeePerGas
309
- // ? BigInt(step.transactionRequest.maxFeePerGas as string)
310
- // : undefined,
311
- maxPriorityFeePerGas:
312
- this.client.account?.type === 'local'
313
- ? await getMaxPriorityFeePerGas(this.client)
314
- : step.transactionRequest.maxPriorityFeePerGas
315
- ? BigInt(step.transactionRequest.maxPriorityFeePerGas)
316
- : undefined,
317
- }
417
+ }
318
418
 
319
- if (this.executionOptions?.updateTransactionRequestHook) {
320
- const customizedTransactionRequest: TransactionParameters =
321
- await this.executionOptions.updateTransactionRequestHook({
322
- requestType: 'transaction',
323
- ...transactionRequest,
324
- })
419
+ if (this.executionOptions?.updateTransactionRequestHook) {
420
+ const customizedTransactionRequest: TransactionParameters =
421
+ await this.executionOptions.updateTransactionRequestHook({
422
+ requestType: 'transaction',
423
+ ...transactionRequest,
424
+ })
325
425
 
326
- transactionRequest = {
327
- ...transactionRequest,
328
- ...customizedTransactionRequest,
329
- }
330
- }
426
+ transactionRequest = {
427
+ ...transactionRequest,
428
+ ...customizedTransactionRequest,
429
+ }
430
+ }
331
431
 
332
- // Make sure that the chain is still correct
333
- const updatedClient = await this.checkClient(step, process)
334
- if (!updatedClient) {
335
- return step
336
- }
432
+ // Make sure that the chain is still correct
433
+ const updatedClient = await this.checkClient(step, process)
434
+ if (!updatedClient) {
435
+ return step
436
+ }
337
437
 
338
- process = this.statusManager.updateProcess(
339
- step,
340
- process.type,
341
- permitSupported ? 'PERMIT_REQUIRED' : 'ACTION_REQUIRED'
342
- )
438
+ process = this.statusManager.updateProcess(
439
+ step,
440
+ process.type,
441
+ 'ACTION_REQUIRED'
442
+ )
343
443
 
344
- if (!this.allowUserInteraction) {
345
- return step
346
- }
444
+ if (!this.allowUserInteraction) {
445
+ return step
446
+ }
347
447
 
348
- let isTransactionRelayed = false
448
+ let txHash: Hash
449
+ let isTransactionRelayed = false
349
450
 
350
- if (atomicBatchSupported) {
351
- const transferCall: Call = {
352
- chainId: fromChain.id,
353
- data: transactionRequest.data as Hex,
354
- to: transactionRequest.to as Address,
355
- value: transactionRequest.value,
356
- }
451
+ if (atomicBatchSupported) {
452
+ const transferCall: Call = {
453
+ chainId: fromChain.id,
454
+ data: transactionRequest.data as Hex,
455
+ to: transactionRequest.to as Address,
456
+ value: transactionRequest.value,
457
+ }
357
458
 
358
- calls.push(transferCall)
359
-
360
- txHash = (await getAction(
361
- this.client,
362
- sendCalls,
363
- 'sendCalls'
364
- )({
365
- account: this.client.account!,
366
- calls,
367
- })) as Address
368
- } else {
369
- let permitSignature: PermitSignature | undefined
370
- if (permitSupported) {
371
- permitSignature = await signPermitMessage(this.client, {
372
- transactionRequest,
373
- chain: fromChain,
374
- tokenAddress: step.action.fromToken.address as Address,
375
- amount: BigInt(step.action.fromAmount),
376
- nativePermit,
377
- permitData: isPermitStep ? step.permitData : undefined,
378
- useWitness: isPermitStep,
379
- })
380
- transactionRequest.to = fromChain.permit2Proxy
381
- }
382
- if (isPermitStep && permitSignature) {
383
- const relayedTransaction = await relayTransaction({
384
- tokenOwner: this.client.account!.address,
385
- chainId: fromChain.id,
386
- permit: step.permit,
387
- witness: step.witness,
388
- signedPermitData: permitSignature.signature,
389
- callData: transactionRequest.data!,
390
- })
391
- txHash = relayedTransaction.data.taskId
392
- isTransactionRelayed = true
393
- } else {
394
- if (permitSignature) {
395
- // If we have a permit signature, we need to use updated data
396
- transactionRequest.data = permitSignature.data
397
- try {
398
- // Try to re-estimate the gas due to additional Permit data
399
- const estimatedGas = await estimateGas(this.client, {
400
- account: this.client.account!,
401
- to: transactionRequest.to as Address,
402
- data: transactionRequest.data as Hex,
403
- value: transactionRequest.value,
404
- })
405
- transactionRequest.gas =
406
- transactionRequest.gas &&
407
- transactionRequest.gas > estimatedGas
408
- ? transactionRequest.gas
409
- : estimatedGas
410
- } catch {
411
- // Let the wallet estimate the gas in case of failure
412
- transactionRequest.gas = undefined
413
- }
414
- }
415
- process = this.statusManager.updateProcess(
416
- step,
417
- process.type,
418
- 'ACTION_REQUIRED'
419
- )
420
- txHash = await getAction(
421
- this.client,
422
- sendTransaction,
423
- 'sendTransaction'
424
- )({
425
- to: transactionRequest.to,
459
+ calls.push(transferCall)
460
+
461
+ txHash = (await getAction(
462
+ this.client,
463
+ sendCalls,
464
+ 'sendCalls'
465
+ )({
466
+ account: this.client.account!,
467
+ calls,
468
+ })) as Address
469
+ } else {
470
+ let permitSignature: PermitSignature | undefined
471
+ if (permitSupported) {
472
+ permitSignature = await signPermitMessage(this.client, {
473
+ transactionRequest,
474
+ chain: fromChain,
475
+ tokenAddress: step.action.fromToken.address as Address,
476
+ amount: BigInt(step.action.fromAmount),
477
+ nativePermit,
478
+ permitData: isRelayerTransaction ? step.permitData : undefined,
479
+ useWitness: isRelayerTransaction,
480
+ })
481
+ transactionRequest.to = fromChain.permit2Proxy
482
+ this.statusManager.updateProcess(step, process.type, 'DONE')
483
+ }
484
+ if (isRelayerTransaction && permitSignature) {
485
+ process = this.statusManager.findOrCreateProcess({
486
+ step,
487
+ type: currentProcessType,
488
+ status: 'PENDING',
489
+ })
490
+ const relayedTransaction = await relayTransaction({
491
+ tokenOwner: this.client.account!.address,
492
+ chainId: fromChain.id,
493
+ permit: step.permit,
494
+ witness: step.witness,
495
+ signedPermitData: permitSignature.signature,
496
+ callData: transactionRequest.data!,
497
+ })
498
+ txHash = relayedTransaction.data.taskId
499
+ isTransactionRelayed = true
500
+ } else {
501
+ process = this.statusManager.findOrCreateProcess({
502
+ step,
503
+ type: currentProcessType,
504
+ status: 'STARTED',
505
+ })
506
+ if (permitSignature) {
507
+ // If we have a permit signature, we need to use updated data
508
+ transactionRequest.data = permitSignature.data
509
+ try {
510
+ // Try to re-estimate the gas due to additional Permit data
511
+ const estimatedGas = await estimateGas(this.client, {
426
512
  account: this.client.account!,
427
- data: transactionRequest.data,
513
+ to: transactionRequest.to as Address,
514
+ data: transactionRequest.data as Hex,
428
515
  value: transactionRequest.value,
429
- gas: transactionRequest.gas,
430
- gasPrice: transactionRequest.gasPrice,
431
- maxFeePerGas: transactionRequest.maxFeePerGas,
432
- maxPriorityFeePerGas: transactionRequest.maxPriorityFeePerGas,
433
- } as SendTransactionParameters)
516
+ })
517
+ transactionRequest.gas =
518
+ transactionRequest.gas && transactionRequest.gas > estimatedGas
519
+ ? transactionRequest.gas
520
+ : estimatedGas
521
+ } catch {
522
+ // Let the wallet estimate the gas in case of failure
523
+ transactionRequest.gas = undefined
434
524
  }
435
525
  }
436
526
  process = this.statusManager.updateProcess(
437
527
  step,
438
528
  process.type,
439
- 'PENDING',
440
- // When atomic batch is supported, txHash represents the batch hash rather than an individual transaction hash at this point
441
- atomicBatchSupported
442
- ? {
443
- atomicBatchSupported,
444
- }
445
- : isTransactionRelayed
446
- ? undefined
447
- : {
448
- txHash: txHash,
449
- txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${txHash}`,
450
- }
529
+ 'ACTION_REQUIRED'
451
530
  )
452
- }
453
-
454
- let transactionReceipt:
455
- | TransactionReceipt
456
- | WalletCallReceipt
457
- | undefined
458
-
459
- if (atomicBatchSupported) {
460
- transactionReceipt = await waitForBatchTransactionReceipt(
531
+ txHash = await getAction(
461
532
  this.client,
462
- txHash
463
- )
464
- } else if (isPermitStep) {
465
- transactionReceipt = await waitForRelayedTransactionReceipt(txHash)
466
- } else {
467
- transactionReceipt = await waitForTransactionReceipt({
468
- client: this.client,
469
- chainId: fromChain.id,
470
- txHash,
471
- onReplaced: (response) => {
472
- this.statusManager.updateProcess(step, process.type, 'PENDING', {
473
- txHash: response.transaction.hash,
474
- txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
475
- })
476
- },
477
- })
533
+ sendTransaction,
534
+ 'sendTransaction'
535
+ )({
536
+ to: transactionRequest.to,
537
+ account: this.client.account!,
538
+ data: transactionRequest.data,
539
+ value: transactionRequest.value,
540
+ gas: transactionRequest.gas,
541
+ gasPrice: transactionRequest.gasPrice,
542
+ maxFeePerGas: transactionRequest.maxFeePerGas,
543
+ maxPriorityFeePerGas: transactionRequest.maxPriorityFeePerGas,
544
+ } as SendTransactionParameters)
478
545
  }
479
-
480
- // Update pending process if the transaction hash from the receipt is different.
481
- // This might happen if the transaction was replaced.
482
- if (
483
- transactionReceipt?.transactionHash &&
484
- transactionReceipt.transactionHash !== txHash
485
- ) {
486
- process = this.statusManager.updateProcess(
487
- step,
488
- process.type,
489
- 'PENDING',
490
- {
491
- txHash: transactionReceipt.transactionHash,
492
- txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${transactionReceipt.transactionHash}`,
493
- }
494
- )
495
- }
496
-
497
- if (isBridgeExecution) {
498
- process = this.statusManager.updateProcess(step, process.type, 'DONE')
499
- }
500
- } catch (e: any) {
501
- const error = await parseEVMErrors(e, step, process)
502
- process = this.statusManager.updateProcess(
503
- step,
504
- process.type,
505
- 'FAILED',
506
- {
507
- error: {
508
- message: error.cause.message,
509
- code: error.code,
510
- },
511
- }
512
- )
513
- this.statusManager.updateExecution(step, 'FAILED')
514
-
515
- throw error
516
546
  }
517
- }
547
+ process = this.statusManager.updateProcess(
548
+ step,
549
+ process.type,
550
+ 'PENDING',
551
+ // When atomic batch is supported, txHash represents the batch hash rather than an individual transaction hash at this point
552
+ atomicBatchSupported
553
+ ? {
554
+ atomicBatchSupported,
555
+ }
556
+ : isTransactionRelayed
557
+ ? undefined
558
+ : {
559
+ txHash: txHash,
560
+ txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${txHash}`,
561
+ }
562
+ )
518
563
 
519
- // Wait for the transaction status on the destination chain
520
- const transactionHash = process.txHash
521
- if (!transactionHash) {
522
- throw new Error('Transaction hash is undefined.')
523
- }
524
- if (isBridgeExecution) {
525
- process = this.statusManager.findOrCreateProcess({
564
+ await this.waitForTransaction({
526
565
  step,
527
- type: 'RECEIVING_CHAIN',
528
- status: 'PENDING',
529
- chainId: toChain.id,
566
+ process,
567
+ fromChain,
568
+ toChain,
569
+ atomicBatchSupported,
570
+ isRelayerTransaction,
571
+ txHash,
572
+ isBridgeExecution,
530
573
  })
531
- }
532
574
 
533
- await waitForDestinationChainTransaction(
534
- step,
535
- process.type,
536
- transactionHash,
537
- toChain,
538
- this.statusManager
539
- )
575
+ // DONE
576
+ return step
577
+ } catch (e: any) {
578
+ const error = await parseEVMErrors(e, step, process)
579
+ process = this.statusManager.updateProcess(
580
+ step,
581
+ process?.type || currentProcessType,
582
+ 'FAILED',
583
+ {
584
+ error: {
585
+ message: error.cause.message,
586
+ code: error.code,
587
+ },
588
+ }
589
+ )
590
+ this.statusManager.updateExecution(step, 'FAILED')
540
591
 
541
- // DONE
542
- return step
592
+ throw error
593
+ }
543
594
  }
544
595
  }