@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.
- package/package.json +5 -5
- package/src/_cjs/core/EVM/EVMStepExecutor.js +252 -221
- package/src/_cjs/core/EVM/EVMStepExecutor.js.map +1 -1
- package/src/_cjs/core/EVM/parseEVMErrors.js +2 -1
- package/src/_cjs/core/EVM/parseEVMErrors.js.map +1 -1
- package/src/_cjs/core/EVM/typeguards.js +2 -2
- package/src/_cjs/core/EVM/typeguards.js.map +1 -1
- package/src/_cjs/core/EVM/utils.js +37 -1
- package/src/_cjs/core/EVM/utils.js.map +1 -1
- package/src/_cjs/core/Solana/SolanaStepExecutor.js +1 -13
- package/src/_cjs/core/Solana/SolanaStepExecutor.js.map +1 -1
- package/src/_cjs/core/Solana/parseSolanaErrors.js.map +1 -1
- package/src/_cjs/core/StatusManager.js +13 -9
- package/src/_cjs/core/StatusManager.js.map +1 -1
- package/src/_cjs/core/UTXO/UTXOStepExecutor.js +1 -13
- package/src/_cjs/core/UTXO/UTXOStepExecutor.js.map +1 -1
- package/src/_cjs/core/UTXO/parseUTXOErrors.js.map +1 -1
- package/src/_cjs/core/processMessages.js +22 -15
- package/src/_cjs/core/processMessages.js.map +1 -1
- package/src/_cjs/core/waitForDestinationChainTransaction.js +16 -1
- package/src/_cjs/core/waitForDestinationChainTransaction.js.map +1 -1
- package/src/_cjs/core/waitForTransactionStatus.js.map +1 -1
- package/src/_cjs/errors/SDKError.js.map +1 -1
- package/src/_cjs/index.js +6 -3
- package/src/_cjs/index.js.map +1 -1
- package/src/_cjs/utils/getTransactionMessage.js.map +1 -1
- package/src/_cjs/version.js +1 -1
- package/src/_esm/core/EVM/EVMStepExecutor.js +276 -244
- package/src/_esm/core/EVM/EVMStepExecutor.js.map +1 -1
- package/src/_esm/core/EVM/parseEVMErrors.js +2 -1
- package/src/_esm/core/EVM/parseEVMErrors.js.map +1 -1
- package/src/_esm/core/EVM/typeguards.js +1 -1
- package/src/_esm/core/EVM/typeguards.js.map +1 -1
- package/src/_esm/core/EVM/utils.js +34 -0
- package/src/_esm/core/EVM/utils.js.map +1 -1
- package/src/_esm/core/Solana/SolanaStepExecutor.js +1 -14
- package/src/_esm/core/Solana/SolanaStepExecutor.js.map +1 -1
- package/src/_esm/core/Solana/parseSolanaErrors.js.map +1 -1
- package/src/_esm/core/StatusManager.js +24 -18
- package/src/_esm/core/StatusManager.js.map +1 -1
- package/src/_esm/core/UTXO/UTXOStepExecutor.js +1 -14
- package/src/_esm/core/UTXO/UTXOStepExecutor.js.map +1 -1
- package/src/_esm/core/UTXO/parseUTXOErrors.js.map +1 -1
- package/src/_esm/core/processMessages.js +22 -15
- package/src/_esm/core/processMessages.js.map +1 -1
- package/src/_esm/core/waitForDestinationChainTransaction.js +17 -1
- package/src/_esm/core/waitForDestinationChainTransaction.js.map +1 -1
- package/src/_esm/core/waitForTransactionStatus.js.map +1 -1
- package/src/_esm/errors/SDKError.js.map +1 -1
- package/src/_esm/index.js +2 -1
- package/src/_esm/index.js.map +1 -1
- package/src/_esm/utils/getTransactionMessage.js.map +1 -1
- package/src/_esm/version.js +1 -1
- package/src/_types/core/EVM/EVMStepExecutor.d.ts +13 -3
- package/src/_types/core/EVM/EVMStepExecutor.d.ts.map +1 -1
- package/src/_types/core/EVM/checkAllowance.d.ts.map +1 -1
- package/src/_types/core/EVM/parseEVMErrors.d.ts +2 -1
- package/src/_types/core/EVM/parseEVMErrors.d.ts.map +1 -1
- package/src/_types/core/EVM/typeguards.d.ts +1 -1
- package/src/_types/core/EVM/typeguards.d.ts.map +1 -1
- package/src/_types/core/EVM/utils.d.ts +4 -2
- package/src/_types/core/EVM/utils.d.ts.map +1 -1
- package/src/_types/core/Solana/SolanaStepExecutor.d.ts.map +1 -1
- package/src/_types/core/Solana/parseSolanaErrors.d.ts +2 -1
- package/src/_types/core/Solana/parseSolanaErrors.d.ts.map +1 -1
- package/src/_types/core/StatusManager.d.ts +14 -11
- package/src/_types/core/StatusManager.d.ts.map +1 -1
- package/src/_types/core/UTXO/UTXOStepExecutor.d.ts.map +1 -1
- package/src/_types/core/UTXO/parseUTXOErrors.d.ts +2 -1
- package/src/_types/core/UTXO/parseUTXOErrors.d.ts.map +1 -1
- package/src/_types/core/processMessages.d.ts +3 -1
- package/src/_types/core/processMessages.d.ts.map +1 -1
- package/src/_types/core/types.d.ts +32 -1
- package/src/_types/core/types.d.ts.map +1 -1
- package/src/_types/core/waitForDestinationChainTransaction.d.ts +3 -3
- package/src/_types/core/waitForDestinationChainTransaction.d.ts.map +1 -1
- package/src/_types/core/waitForTransactionStatus.d.ts +2 -1
- package/src/_types/core/waitForTransactionStatus.d.ts.map +1 -1
- package/src/_types/errors/SDKError.d.ts +2 -1
- package/src/_types/errors/SDKError.d.ts.map +1 -1
- package/src/_types/index.d.ts +3 -2
- package/src/_types/index.d.ts.map +1 -1
- package/src/_types/utils/getTransactionMessage.d.ts +2 -1
- package/src/_types/utils/getTransactionMessage.d.ts.map +1 -1
- package/src/_types/version.d.ts +1 -1
- package/src/core/EVM/EVMStepExecutor.ts +357 -303
- package/src/core/EVM/checkAllowance.ts +2 -2
- package/src/core/EVM/parseEVMErrors.ts +6 -2
- package/src/core/EVM/typeguards.ts +1 -1
- package/src/core/EVM/utils.ts +53 -2
- package/src/core/Solana/SolanaStepExecutor.ts +2 -16
- package/src/core/Solana/parseSolanaErrors.ts +2 -1
- package/src/core/StatusManager.ts +38 -26
- package/src/core/UTXO/UTXOStepExecutor.ts +2 -16
- package/src/core/UTXO/parseUTXOErrors.ts +2 -1
- package/src/core/processMessages.ts +25 -21
- package/src/core/types.ts +54 -1
- package/src/core/waitForDestinationChainTransaction.ts +21 -4
- package/src/core/waitForTransactionStatus.ts +2 -6
- package/src/errors/SDKError.ts +2 -1
- package/src/index.ts +7 -1
- package/src/utils/getTransactionMessage.ts +2 -1
- package/src/version.ts +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
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 {
|
|
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 (
|
|
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
|
|
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
|
|
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
|
-
!
|
|
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 &&
|
|
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
|
-
!
|
|
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.
|
|
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
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
307
|
+
if (process?.status === 'DONE') {
|
|
308
|
+
await waitForDestinationChainTransaction(
|
|
309
|
+
step,
|
|
310
|
+
process,
|
|
311
|
+
fromChain,
|
|
312
|
+
toChain,
|
|
313
|
+
this.statusManager
|
|
314
|
+
)
|
|
247
315
|
|
|
248
|
-
|
|
249
|
-
|
|
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
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
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
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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
|
-
|
|
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
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
421
|
+
if (this.executionOptions?.updateTransactionRequestHook) {
|
|
422
|
+
const customizedTransactionRequest: TransactionParameters =
|
|
423
|
+
await this.executionOptions.updateTransactionRequestHook({
|
|
424
|
+
requestType: 'transaction',
|
|
425
|
+
...transactionRequest,
|
|
426
|
+
})
|
|
325
427
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
428
|
+
transactionRequest = {
|
|
429
|
+
...transactionRequest,
|
|
430
|
+
...customizedTransactionRequest,
|
|
431
|
+
}
|
|
432
|
+
}
|
|
331
433
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
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
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
440
|
+
process = this.statusManager.updateProcess(
|
|
441
|
+
step,
|
|
442
|
+
process.type,
|
|
443
|
+
'ACTION_REQUIRED'
|
|
444
|
+
)
|
|
343
445
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
446
|
+
if (!this.allowUserInteraction) {
|
|
447
|
+
return step
|
|
448
|
+
}
|
|
347
449
|
|
|
348
|
-
|
|
450
|
+
let txHash: Hash
|
|
451
|
+
let isTransactionRelayed = false
|
|
349
452
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
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
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
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
|
-
|
|
515
|
+
to: transactionRequest.to as Address,
|
|
516
|
+
data: transactionRequest.data as Hex,
|
|
428
517
|
value: transactionRequest.value,
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
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
|
-
'
|
|
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
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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
|
-
|
|
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
|
-
|
|
528
|
-
|
|
529
|
-
|
|
569
|
+
process,
|
|
570
|
+
fromChain,
|
|
571
|
+
toChain,
|
|
572
|
+
atomicBatchSupported,
|
|
573
|
+
isRelayerTransaction,
|
|
574
|
+
txHash,
|
|
575
|
+
isBridgeExecution,
|
|
530
576
|
})
|
|
531
|
-
}
|
|
532
577
|
|
|
533
|
-
|
|
534
|
-
step
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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
|
-
|
|
542
|
-
|
|
595
|
+
throw error
|
|
596
|
+
}
|
|
543
597
|
}
|
|
544
598
|
}
|