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

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