@lifi/sdk 3.6.0-beta.2 → 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 (114) hide show
  1. package/package.json +4 -4
  2. package/src/_cjs/core/EVM/EVMStepExecutor.js +250 -211
  3. package/src/_cjs/core/EVM/EVMStepExecutor.js.map +1 -1
  4. package/src/_cjs/core/EVM/getNativePermit.js +127 -59
  5. package/src/_cjs/core/EVM/getNativePermit.js.map +1 -1
  6. package/src/_cjs/core/EVM/parseEVMErrors.js +2 -1
  7. package/src/_cjs/core/EVM/parseEVMErrors.js.map +1 -1
  8. package/src/_cjs/core/EVM/signPermitMessage.js +1 -7
  9. package/src/_cjs/core/EVM/signPermitMessage.js.map +1 -1
  10. package/src/_cjs/core/EVM/typeguards.js +3 -3
  11. package/src/_cjs/core/EVM/typeguards.js.map +1 -1
  12. package/src/_cjs/core/Solana/SolanaStepExecutor.js +1 -13
  13. package/src/_cjs/core/Solana/SolanaStepExecutor.js.map +1 -1
  14. package/src/_cjs/core/Solana/parseSolanaErrors.js.map +1 -1
  15. package/src/_cjs/core/StatusManager.js +13 -9
  16. package/src/_cjs/core/StatusManager.js.map +1 -1
  17. package/src/_cjs/core/UTXO/UTXOStepExecutor.js +1 -13
  18. package/src/_cjs/core/UTXO/UTXOStepExecutor.js.map +1 -1
  19. package/src/_cjs/core/UTXO/getUTXOAPIPublicClient.js +3 -3
  20. package/src/_cjs/core/UTXO/getUTXOAPIPublicClient.js.map +1 -1
  21. package/src/_cjs/core/UTXO/parseUTXOErrors.js.map +1 -1
  22. package/src/_cjs/core/processMessages.js +22 -15
  23. package/src/_cjs/core/processMessages.js.map +1 -1
  24. package/src/_cjs/core/waitForDestinationChainTransaction.js +16 -1
  25. package/src/_cjs/core/waitForDestinationChainTransaction.js.map +1 -1
  26. package/src/_cjs/core/waitForTransactionStatus.js.map +1 -1
  27. package/src/_cjs/errors/SDKError.js.map +1 -1
  28. package/src/_cjs/index.js +2 -2
  29. package/src/_cjs/index.js.map +1 -1
  30. package/src/_cjs/utils/getTransactionMessage.js.map +1 -1
  31. package/src/_cjs/version.js +1 -1
  32. package/src/_esm/core/EVM/EVMStepExecutor.js +273 -233
  33. package/src/_esm/core/EVM/EVMStepExecutor.js.map +1 -1
  34. package/src/_esm/core/EVM/getNativePermit.js +147 -60
  35. package/src/_esm/core/EVM/getNativePermit.js.map +1 -1
  36. package/src/_esm/core/EVM/parseEVMErrors.js +2 -1
  37. package/src/_esm/core/EVM/parseEVMErrors.js.map +1 -1
  38. package/src/_esm/core/EVM/signPermitMessage.js +1 -7
  39. package/src/_esm/core/EVM/signPermitMessage.js.map +1 -1
  40. package/src/_esm/core/EVM/typeguards.js +2 -2
  41. package/src/_esm/core/EVM/typeguards.js.map +1 -1
  42. package/src/_esm/core/Solana/SolanaStepExecutor.js +1 -14
  43. package/src/_esm/core/Solana/SolanaStepExecutor.js.map +1 -1
  44. package/src/_esm/core/Solana/parseSolanaErrors.js.map +1 -1
  45. package/src/_esm/core/StatusManager.js +24 -18
  46. package/src/_esm/core/StatusManager.js.map +1 -1
  47. package/src/_esm/core/UTXO/UTXOStepExecutor.js +1 -14
  48. package/src/_esm/core/UTXO/UTXOStepExecutor.js.map +1 -1
  49. package/src/_esm/core/UTXO/getUTXOAPIPublicClient.js +3 -3
  50. package/src/_esm/core/UTXO/getUTXOAPIPublicClient.js.map +1 -1
  51. package/src/_esm/core/UTXO/parseUTXOErrors.js.map +1 -1
  52. package/src/_esm/core/processMessages.js +22 -15
  53. package/src/_esm/core/processMessages.js.map +1 -1
  54. package/src/_esm/core/waitForDestinationChainTransaction.js +17 -1
  55. package/src/_esm/core/waitForDestinationChainTransaction.js.map +1 -1
  56. package/src/_esm/core/waitForTransactionStatus.js.map +1 -1
  57. package/src/_esm/errors/SDKError.js.map +1 -1
  58. package/src/_esm/index.js +1 -1
  59. package/src/_esm/index.js.map +1 -1
  60. package/src/_esm/utils/getTransactionMessage.js.map +1 -1
  61. package/src/_esm/version.js +1 -1
  62. package/src/_types/core/EVM/EVMStepExecutor.d.ts +13 -3
  63. package/src/_types/core/EVM/EVMStepExecutor.d.ts.map +1 -1
  64. package/src/_types/core/EVM/checkAllowance.d.ts.map +1 -1
  65. package/src/_types/core/EVM/getNativePermit.d.ts +2 -0
  66. package/src/_types/core/EVM/getNativePermit.d.ts.map +1 -1
  67. package/src/_types/core/EVM/parseEVMErrors.d.ts +2 -1
  68. package/src/_types/core/EVM/parseEVMErrors.d.ts.map +1 -1
  69. package/src/_types/core/EVM/signPermitMessage.d.ts.map +1 -1
  70. package/src/_types/core/EVM/typeguards.d.ts +1 -1
  71. package/src/_types/core/EVM/typeguards.d.ts.map +1 -1
  72. package/src/_types/core/Solana/SolanaStepExecutor.d.ts.map +1 -1
  73. package/src/_types/core/Solana/parseSolanaErrors.d.ts +2 -1
  74. package/src/_types/core/Solana/parseSolanaErrors.d.ts.map +1 -1
  75. package/src/_types/core/StatusManager.d.ts +14 -11
  76. package/src/_types/core/StatusManager.d.ts.map +1 -1
  77. package/src/_types/core/UTXO/UTXOStepExecutor.d.ts.map +1 -1
  78. package/src/_types/core/UTXO/parseUTXOErrors.d.ts +2 -1
  79. package/src/_types/core/UTXO/parseUTXOErrors.d.ts.map +1 -1
  80. package/src/_types/core/processMessages.d.ts +3 -1
  81. package/src/_types/core/processMessages.d.ts.map +1 -1
  82. package/src/_types/core/types.d.ts +32 -1
  83. package/src/_types/core/types.d.ts.map +1 -1
  84. package/src/_types/core/waitForDestinationChainTransaction.d.ts +3 -3
  85. package/src/_types/core/waitForDestinationChainTransaction.d.ts.map +1 -1
  86. package/src/_types/core/waitForTransactionStatus.d.ts +2 -1
  87. package/src/_types/core/waitForTransactionStatus.d.ts.map +1 -1
  88. package/src/_types/errors/SDKError.d.ts +2 -1
  89. package/src/_types/errors/SDKError.d.ts.map +1 -1
  90. package/src/_types/index.d.ts +2 -2
  91. package/src/_types/index.d.ts.map +1 -1
  92. package/src/_types/utils/getTransactionMessage.d.ts +2 -1
  93. package/src/_types/utils/getTransactionMessage.d.ts.map +1 -1
  94. package/src/_types/version.d.ts +1 -1
  95. package/src/core/EVM/EVMStepExecutor.ts +353 -293
  96. package/src/core/EVM/checkAllowance.ts +2 -2
  97. package/src/core/EVM/getNativePermit.ts +219 -66
  98. package/src/core/EVM/parseEVMErrors.ts +6 -2
  99. package/src/core/EVM/signPermitMessage.ts +1 -8
  100. package/src/core/EVM/typeguards.ts +2 -2
  101. package/src/core/Solana/SolanaStepExecutor.ts +2 -16
  102. package/src/core/Solana/parseSolanaErrors.ts +2 -1
  103. package/src/core/StatusManager.ts +38 -26
  104. package/src/core/UTXO/UTXOStepExecutor.ts +2 -16
  105. package/src/core/UTXO/getUTXOAPIPublicClient.ts +3 -3
  106. package/src/core/UTXO/parseUTXOErrors.ts +2 -1
  107. package/src/core/processMessages.ts +25 -21
  108. package/src/core/types.ts +54 -1
  109. package/src/core/waitForDestinationChainTransaction.ts +21 -4
  110. package/src/core/waitForTransactionStatus.ts +2 -6
  111. package/src/errors/SDKError.ts +2 -1
  112. package/src/index.ts +6 -1
  113. package/src/utils/getTransactionMessage.ts +2 -1
  114. 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,316 +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
+ }
316
+
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
+ })
287
347
 
288
- if (!step.transactionRequest) {
289
- throw new TransactionError(
290
- LiFiErrorCode.TransactionUnprepared,
291
- 'Unable to prepare transaction.'
292
- )
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
- if (atomicBatchSupported) {
349
- const transferCall: Call = {
350
- chainId: fromChain.id,
351
- data: transactionRequest.data as Hex,
352
- to: transactionRequest.to as Address,
353
- value: transactionRequest.value,
354
- }
448
+ let txHash: Hash
449
+ let isTransactionRelayed = false
355
450
 
356
- calls.push(transferCall)
357
-
358
- txHash = (await getAction(
359
- this.client,
360
- sendCalls,
361
- 'sendCalls'
362
- )({
363
- account: this.client.account!,
364
- calls,
365
- })) as Address
366
- } else {
367
- let permitSignature: PermitSignature | undefined
368
- if (permitSupported) {
369
- permitSignature = await signPermitMessage(this.client, {
370
- transactionRequest,
371
- chain: fromChain,
372
- tokenAddress: step.action.fromToken.address as Address,
373
- amount: BigInt(step.action.fromAmount),
374
- nativePermit,
375
- permitData: isPermitStep ? step.permitData : undefined,
376
- useWitness: isPermitStep,
377
- })
378
- transactionRequest.to = fromChain.permit2Proxy
379
- }
380
- if (isPermitStep && permitSignature) {
381
- const relayedTransaction = await relayTransaction({
382
- tokenOwner: this.client.account!.address,
383
- chainId: fromChain.id,
384
- permit: step.permit,
385
- witness: step.witness,
386
- signedPermitData: permitSignature.signature,
387
- callData: transactionRequest.data!,
388
- })
389
- txHash = relayedTransaction.data.taskId
390
- } else {
391
- if (permitSignature) {
392
- // If we have a permit signature, we need to use updated data
393
- transactionRequest.data = permitSignature.data
394
- try {
395
- // Try to re-estimate the gas due to additional Permit data
396
- transactionRequest.gas = await estimateGas(this.client, {
397
- account: this.client.account!,
398
- to: transactionRequest.to as Address,
399
- data: transactionRequest.data as Hex,
400
- value: transactionRequest.value,
401
- })
402
- } catch {
403
- // Let the wallet estimate the gas in case of failure
404
- transactionRequest.gas = undefined
405
- }
406
- }
407
- process = this.statusManager.updateProcess(
408
- step,
409
- process.type,
410
- 'ACTION_REQUIRED'
411
- )
412
- txHash = await getAction(
413
- this.client,
414
- sendTransaction,
415
- 'sendTransaction'
416
- )({
417
- to: transactionRequest.to,
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
+ }
458
+
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, {
418
512
  account: this.client.account!,
419
- data: transactionRequest.data,
513
+ to: transactionRequest.to as Address,
514
+ data: transactionRequest.data as Hex,
420
515
  value: transactionRequest.value,
421
- gas: transactionRequest.gas,
422
- gasPrice: transactionRequest.gasPrice,
423
- maxFeePerGas: transactionRequest.maxFeePerGas,
424
- maxPriorityFeePerGas: transactionRequest.maxPriorityFeePerGas,
425
- } 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
426
524
  }
427
525
  }
428
-
429
526
  process = this.statusManager.updateProcess(
430
527
  step,
431
528
  process.type,
432
- 'PENDING',
433
- // When atomic batch is supported, txHash represents the batch hash rather than an individual transaction hash at this point
434
- atomicBatchSupported
435
- ? {
436
- atomicBatchSupported,
437
- }
438
- : {
439
- txHash: txHash,
440
- txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${txHash}`,
441
- }
529
+ 'ACTION_REQUIRED'
442
530
  )
443
- }
444
-
445
- let transactionReceipt:
446
- | TransactionReceipt
447
- | WalletCallReceipt
448
- | undefined
449
-
450
- if (atomicBatchSupported) {
451
- transactionReceipt = await waitForBatchTransactionReceipt(
531
+ txHash = await getAction(
452
532
  this.client,
453
- txHash
454
- )
455
- } else if (isPermitStep) {
456
- transactionReceipt = await waitForRelayedTransactionReceipt(txHash)
457
- } else {
458
- transactionReceipt = await waitForTransactionReceipt({
459
- client: this.client,
460
- chainId: fromChain.id,
461
- txHash,
462
- onReplaced: (response) => {
463
- this.statusManager.updateProcess(step, process.type, 'PENDING', {
464
- txHash: response.transaction.hash,
465
- txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
466
- })
467
- },
468
- })
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)
469
545
  }
470
-
471
- // Update pending process if the transaction hash from the receipt is different.
472
- // This might happen if the transaction was replaced.
473
- if (
474
- transactionReceipt?.transactionHash &&
475
- transactionReceipt.transactionHash !== txHash
476
- ) {
477
- process = this.statusManager.updateProcess(
478
- step,
479
- process.type,
480
- 'PENDING',
481
- {
482
- txHash: transactionReceipt.transactionHash,
483
- txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${transactionReceipt.transactionHash}`,
484
- }
485
- )
486
- }
487
-
488
- if (isBridgeExecution) {
489
- process = this.statusManager.updateProcess(step, process.type, 'DONE')
490
- }
491
- } catch (e: any) {
492
- const error = await parseEVMErrors(e, step, process)
493
- process = this.statusManager.updateProcess(
494
- step,
495
- process.type,
496
- 'FAILED',
497
- {
498
- error: {
499
- message: error.cause.message,
500
- code: error.code,
501
- },
502
- }
503
- )
504
- this.statusManager.updateExecution(step, 'FAILED')
505
-
506
- throw error
507
546
  }
508
- }
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
+ )
509
563
 
510
- // Wait for the transaction status on the destination chain
511
- const transactionHash = process.txHash
512
- if (!transactionHash) {
513
- throw new Error('Transaction hash is undefined.')
514
- }
515
- if (isBridgeExecution) {
516
- process = this.statusManager.findOrCreateProcess({
564
+ await this.waitForTransaction({
517
565
  step,
518
- type: 'RECEIVING_CHAIN',
519
- status: 'PENDING',
520
- chainId: toChain.id,
566
+ process,
567
+ fromChain,
568
+ toChain,
569
+ atomicBatchSupported,
570
+ isRelayerTransaction,
571
+ txHash,
572
+ isBridgeExecution,
521
573
  })
522
- }
523
574
 
524
- await waitForDestinationChainTransaction(
525
- step,
526
- process.type,
527
- transactionHash,
528
- toChain,
529
- this.statusManager
530
- )
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')
531
591
 
532
- // DONE
533
- return step
592
+ throw error
593
+ }
534
594
  }
535
595
  }