@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
|
@@ -5,7 +5,6 @@ import { config } from '../../config.js';
|
|
|
5
5
|
import { LiFiErrorCode } from '../../errors/constants.js';
|
|
6
6
|
import { TransactionError } from '../../errors/errors.js';
|
|
7
7
|
import { getRelayerQuote, getStepTransaction, relayTransaction, } from '../../services/api.js';
|
|
8
|
-
import { isZeroAddress } from '../../utils/isZeroAddress.js';
|
|
9
8
|
import { BaseStepExecutor } from '../BaseStepExecutor.js';
|
|
10
9
|
import { checkBalance } from '../checkBalance.js';
|
|
11
10
|
import { stepComparison } from '../stepComparison.js';
|
|
@@ -15,8 +14,8 @@ import { getNativePermit } from './getNativePermit.js';
|
|
|
15
14
|
import { parseEVMErrors } from './parseEVMErrors.js';
|
|
16
15
|
import { signPermitMessage } from './signPermitMessage.js';
|
|
17
16
|
import { switchChain } from './switchChain.js';
|
|
18
|
-
import {
|
|
19
|
-
import { getMaxPriorityFeePerGas } from './utils.js';
|
|
17
|
+
import { isRelayerStep } from './typeguards.js';
|
|
18
|
+
import { convertExtendedChain, getMaxPriorityFeePerGas } from './utils.js';
|
|
20
19
|
import { waitForBatchTransactionReceipt, } from './waitForBatchTransactionReceipt.js';
|
|
21
20
|
import { waitForRelayedTransactionReceipt } from './waitForRelayedTransactionReceipt.js';
|
|
22
21
|
import { waitForTransactionReceipt } from './waitForTransactionReceipt.js';
|
|
@@ -45,7 +44,7 @@ export class EVMStepExecutor extends BaseStepExecutor {
|
|
|
45
44
|
const accountAddresses = (await getAction(this.client, getAddresses, 'getAddresses')(undefined));
|
|
46
45
|
accountAddress = accountAddresses?.[0];
|
|
47
46
|
}
|
|
48
|
-
if (accountAddress !== step.action.fromAddress) {
|
|
47
|
+
if (accountAddress?.toLowerCase() !== step.action.fromAddress?.toLowerCase()) {
|
|
49
48
|
let processToUpdate = process;
|
|
50
49
|
if (!processToUpdate) {
|
|
51
50
|
// We need to create some process if we don't have one so we can show the error
|
|
@@ -67,6 +66,46 @@ export class EVMStepExecutor extends BaseStepExecutor {
|
|
|
67
66
|
return updatedClient;
|
|
68
67
|
}
|
|
69
68
|
});
|
|
69
|
+
Object.defineProperty(this, "waitForTransaction", {
|
|
70
|
+
enumerable: true,
|
|
71
|
+
configurable: true,
|
|
72
|
+
writable: true,
|
|
73
|
+
value: async ({ step, process, fromChain, toChain, atomicBatchSupported, isRelayerTransaction, txHash, isBridgeExecution, }) => {
|
|
74
|
+
let transactionReceipt;
|
|
75
|
+
if (atomicBatchSupported) {
|
|
76
|
+
transactionReceipt = await waitForBatchTransactionReceipt(this.client, txHash);
|
|
77
|
+
}
|
|
78
|
+
else if (isRelayerTransaction) {
|
|
79
|
+
transactionReceipt = await waitForRelayedTransactionReceipt(txHash);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
transactionReceipt = await waitForTransactionReceipt({
|
|
83
|
+
client: this.client,
|
|
84
|
+
chainId: fromChain.id,
|
|
85
|
+
txHash,
|
|
86
|
+
onReplaced: (response) => {
|
|
87
|
+
this.statusManager.updateProcess(step, process.type, 'PENDING', {
|
|
88
|
+
txHash: response.transaction.hash,
|
|
89
|
+
txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
// Update pending process if the transaction hash from the receipt is different.
|
|
95
|
+
// This might happen if the transaction was replaced.
|
|
96
|
+
if (transactionReceipt?.transactionHash &&
|
|
97
|
+
transactionReceipt.transactionHash !== txHash) {
|
|
98
|
+
process = this.statusManager.updateProcess(step, process.type, 'PENDING', {
|
|
99
|
+
txHash: transactionReceipt.transactionHash,
|
|
100
|
+
txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${transactionReceipt.transactionHash}`,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
if (isBridgeExecution) {
|
|
104
|
+
process = this.statusManager.updateProcess(step, process.type, 'DONE');
|
|
105
|
+
}
|
|
106
|
+
await waitForDestinationChainTransaction(step, process, fromChain, toChain, this.statusManager);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
70
109
|
Object.defineProperty(this, "executeStep", {
|
|
71
110
|
enumerable: true,
|
|
72
111
|
configurable: true,
|
|
@@ -87,21 +126,24 @@ export class EVMStepExecutor extends BaseStepExecutor {
|
|
|
87
126
|
}
|
|
88
127
|
const fromChain = await config.getChainById(step.action.fromChainId);
|
|
89
128
|
const toChain = await config.getChainById(step.action.toChainId);
|
|
129
|
+
// Check if the wallet supports atomic batch transactions (EIP-5792)
|
|
130
|
+
const calls = [];
|
|
90
131
|
let atomicBatchSupported = false;
|
|
91
132
|
try {
|
|
92
133
|
const capabilities = (await getAction(this.client, getCapabilities, 'getCapabilities')(undefined));
|
|
93
134
|
atomicBatchSupported = capabilities[fromChain.id]?.atomicBatch?.supported;
|
|
94
135
|
}
|
|
95
136
|
catch {
|
|
96
|
-
// If the wallet does not support getCapabilities
|
|
137
|
+
// If the wallet does not support getCapabilities or the call fails,
|
|
138
|
+
// we assume that atomic batch is not supported
|
|
97
139
|
}
|
|
98
|
-
const calls = [];
|
|
99
140
|
const isBridgeExecution = fromChain.id !== toChain.id;
|
|
100
141
|
const currentProcessType = isBridgeExecution ? 'CROSS_CHAIN' : 'SWAP';
|
|
101
142
|
// Find existing swap/bridge process
|
|
102
143
|
const existingProcess = step.execution.process.find((p) => p.type === currentProcessType);
|
|
144
|
+
const isFromNativeToken = fromChain.nativeToken.address === step.action.fromToken.address;
|
|
103
145
|
// Check if step requires permit signature and will be used with relayer service
|
|
104
|
-
const
|
|
146
|
+
const isRelayerTransaction = isRelayerStep(step);
|
|
105
147
|
// Check if token requires approval
|
|
106
148
|
// Native tokens (like ETH) don't need approval since they're not ERC20 tokens
|
|
107
149
|
// We should support different permit types:
|
|
@@ -110,19 +152,23 @@ export class EVMStepExecutor extends BaseStepExecutor {
|
|
|
110
152
|
// 3. Standard ERC20 approval
|
|
111
153
|
const nativePermit = await getNativePermit(this.client, fromChain, step.action.fromToken.address);
|
|
112
154
|
// Check if proxy contract is available and token supports native permits, not available for atomic batch
|
|
113
|
-
const nativePermitSupported =
|
|
114
|
-
|
|
155
|
+
const nativePermitSupported = nativePermit.supported &&
|
|
156
|
+
!!fromChain.permit2Proxy &&
|
|
115
157
|
!atomicBatchSupported &&
|
|
116
|
-
!
|
|
158
|
+
!isRelayerTransaction && // TODO: remove once we support ERC-2771
|
|
159
|
+
!isFromNativeToken;
|
|
117
160
|
// Check if chain has Permit2 contract deployed. Permit2 should not be available for atomic batch.
|
|
118
|
-
const permit2Supported = !!fromChain.permit2 &&
|
|
161
|
+
const permit2Supported = !!fromChain.permit2 &&
|
|
162
|
+
!!fromChain.permit2Proxy &&
|
|
163
|
+
!atomicBatchSupported &&
|
|
164
|
+
!isFromNativeToken;
|
|
119
165
|
// Token supports either native permits or Permit2
|
|
120
166
|
const permitSupported = permit2Supported || nativePermitSupported;
|
|
121
167
|
const checkForAllowance =
|
|
122
168
|
// No existing swap/bridgetransaction is pending
|
|
123
169
|
!existingProcess?.txHash &&
|
|
124
170
|
// Token is not native (address is not zero)
|
|
125
|
-
!
|
|
171
|
+
!isFromNativeToken &&
|
|
126
172
|
// Token doesn't support native permits
|
|
127
173
|
!nativePermitSupported;
|
|
128
174
|
if (checkForAllowance) {
|
|
@@ -149,252 +195,238 @@ export class EVMStepExecutor extends BaseStepExecutor {
|
|
|
149
195
|
}
|
|
150
196
|
}
|
|
151
197
|
}
|
|
152
|
-
let process = this.statusManager.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (!updatedClient) {
|
|
164
|
-
return step;
|
|
165
|
-
}
|
|
166
|
-
// Wait for exiting transaction
|
|
167
|
-
txHash = process.txHash;
|
|
198
|
+
let process = this.statusManager.findProcess(step, currentProcessType);
|
|
199
|
+
if (process?.status === 'DONE') {
|
|
200
|
+
await waitForDestinationChainTransaction(step, process, fromChain, toChain, this.statusManager);
|
|
201
|
+
return step;
|
|
202
|
+
}
|
|
203
|
+
try {
|
|
204
|
+
if (process?.txHash) {
|
|
205
|
+
// Make sure that the chain is still correct
|
|
206
|
+
const updatedClient = await this.checkClient(step, process);
|
|
207
|
+
if (!updatedClient) {
|
|
208
|
+
return step;
|
|
168
209
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
data: step.transactionRequest.data,
|
|
211
|
-
value: step.transactionRequest.value
|
|
212
|
-
? BigInt(step.transactionRequest.value)
|
|
213
|
-
: undefined,
|
|
214
|
-
gas: step.transactionRequest.gasLimit
|
|
215
|
-
? BigInt(step.transactionRequest.gasLimit)
|
|
216
|
-
: undefined,
|
|
217
|
-
// gasPrice: step.transactionRequest.gasPrice
|
|
218
|
-
// ? BigInt(step.transactionRequest.gasPrice as string)
|
|
219
|
-
// : undefined,
|
|
220
|
-
// maxFeePerGas: step.transactionRequest.maxFeePerGas
|
|
221
|
-
// ? BigInt(step.transactionRequest.maxFeePerGas as string)
|
|
222
|
-
// : undefined,
|
|
223
|
-
maxPriorityFeePerGas: this.client.account?.type === 'local'
|
|
224
|
-
? await getMaxPriorityFeePerGas(this.client)
|
|
225
|
-
: step.transactionRequest.maxPriorityFeePerGas
|
|
226
|
-
? BigInt(step.transactionRequest.maxPriorityFeePerGas)
|
|
227
|
-
: undefined,
|
|
210
|
+
// Wait for exiting transaction
|
|
211
|
+
const txHash = process.txHash;
|
|
212
|
+
await this.waitForTransaction({
|
|
213
|
+
step,
|
|
214
|
+
process,
|
|
215
|
+
fromChain,
|
|
216
|
+
toChain,
|
|
217
|
+
atomicBatchSupported,
|
|
218
|
+
isRelayerTransaction,
|
|
219
|
+
txHash,
|
|
220
|
+
isBridgeExecution,
|
|
221
|
+
});
|
|
222
|
+
return step;
|
|
223
|
+
}
|
|
224
|
+
process = this.statusManager.findOrCreateProcess({
|
|
225
|
+
step,
|
|
226
|
+
type: permitSupported ? 'PERMIT' : currentProcessType,
|
|
227
|
+
status: 'STARTED',
|
|
228
|
+
});
|
|
229
|
+
// Check balance
|
|
230
|
+
await checkBalance(this.client.account.address, step);
|
|
231
|
+
// Create new transaction request
|
|
232
|
+
if (!step.transactionRequest) {
|
|
233
|
+
const { execution, ...stepBase } = step;
|
|
234
|
+
let updatedStep;
|
|
235
|
+
if (isRelayerTransaction) {
|
|
236
|
+
const updatedRelayedStep = await getRelayerQuote({
|
|
237
|
+
fromChain: stepBase.action.fromChainId,
|
|
238
|
+
fromToken: stepBase.action.fromToken.address,
|
|
239
|
+
fromAddress: stepBase.action.fromAddress,
|
|
240
|
+
fromAmount: stepBase.action.fromAmount,
|
|
241
|
+
toChain: stepBase.action.toChainId,
|
|
242
|
+
toToken: stepBase.action.toToken.address,
|
|
243
|
+
slippage: stepBase.action.slippage,
|
|
244
|
+
toAddress: stepBase.action.toAddress,
|
|
245
|
+
allowBridges: [stepBase.tool],
|
|
246
|
+
});
|
|
247
|
+
updatedStep = {
|
|
248
|
+
...updatedRelayedStep.data.quote.step,
|
|
249
|
+
...updatedRelayedStep.data.quote,
|
|
250
|
+
id: stepBase.id,
|
|
228
251
|
};
|
|
229
|
-
if (this.executionOptions?.updateTransactionRequestHook) {
|
|
230
|
-
const customizedTransactionRequest = await this.executionOptions.updateTransactionRequestHook({
|
|
231
|
-
requestType: 'transaction',
|
|
232
|
-
...transactionRequest,
|
|
233
|
-
});
|
|
234
|
-
transactionRequest = {
|
|
235
|
-
...transactionRequest,
|
|
236
|
-
...customizedTransactionRequest,
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
// Make sure that the chain is still correct
|
|
240
|
-
const updatedClient = await this.checkClient(step, process);
|
|
241
|
-
if (!updatedClient) {
|
|
242
|
-
return step;
|
|
243
|
-
}
|
|
244
|
-
process = this.statusManager.updateProcess(step, process.type, permitSupported ? 'PERMIT_REQUIRED' : 'ACTION_REQUIRED');
|
|
245
|
-
if (!this.allowUserInteraction) {
|
|
246
|
-
return step;
|
|
247
|
-
}
|
|
248
|
-
let isTransactionRelayed = false;
|
|
249
|
-
if (atomicBatchSupported) {
|
|
250
|
-
const transferCall = {
|
|
251
|
-
chainId: fromChain.id,
|
|
252
|
-
data: transactionRequest.data,
|
|
253
|
-
to: transactionRequest.to,
|
|
254
|
-
value: transactionRequest.value,
|
|
255
|
-
};
|
|
256
|
-
calls.push(transferCall);
|
|
257
|
-
txHash = (await getAction(this.client, sendCalls, 'sendCalls')({
|
|
258
|
-
account: this.client.account,
|
|
259
|
-
calls,
|
|
260
|
-
}));
|
|
261
|
-
}
|
|
262
|
-
else {
|
|
263
|
-
let permitSignature;
|
|
264
|
-
if (permitSupported) {
|
|
265
|
-
permitSignature = await signPermitMessage(this.client, {
|
|
266
|
-
transactionRequest,
|
|
267
|
-
chain: fromChain,
|
|
268
|
-
tokenAddress: step.action.fromToken.address,
|
|
269
|
-
amount: BigInt(step.action.fromAmount),
|
|
270
|
-
nativePermit,
|
|
271
|
-
permitData: isPermitStep ? step.permitData : undefined,
|
|
272
|
-
useWitness: isPermitStep,
|
|
273
|
-
});
|
|
274
|
-
transactionRequest.to = fromChain.permit2Proxy;
|
|
275
|
-
}
|
|
276
|
-
if (isPermitStep && permitSignature) {
|
|
277
|
-
const relayedTransaction = await relayTransaction({
|
|
278
|
-
tokenOwner: this.client.account.address,
|
|
279
|
-
chainId: fromChain.id,
|
|
280
|
-
permit: step.permit,
|
|
281
|
-
witness: step.witness,
|
|
282
|
-
signedPermitData: permitSignature.signature,
|
|
283
|
-
callData: transactionRequest.data,
|
|
284
|
-
});
|
|
285
|
-
txHash = relayedTransaction.data.taskId;
|
|
286
|
-
isTransactionRelayed = true;
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
if (permitSignature) {
|
|
290
|
-
// If we have a permit signature, we need to use updated data
|
|
291
|
-
transactionRequest.data = permitSignature.data;
|
|
292
|
-
try {
|
|
293
|
-
// Try to re-estimate the gas due to additional Permit data
|
|
294
|
-
const estimatedGas = await estimateGas(this.client, {
|
|
295
|
-
account: this.client.account,
|
|
296
|
-
to: transactionRequest.to,
|
|
297
|
-
data: transactionRequest.data,
|
|
298
|
-
value: transactionRequest.value,
|
|
299
|
-
});
|
|
300
|
-
transactionRequest.gas =
|
|
301
|
-
transactionRequest.gas &&
|
|
302
|
-
transactionRequest.gas > estimatedGas
|
|
303
|
-
? transactionRequest.gas
|
|
304
|
-
: estimatedGas;
|
|
305
|
-
}
|
|
306
|
-
catch {
|
|
307
|
-
// Let the wallet estimate the gas in case of failure
|
|
308
|
-
transactionRequest.gas = undefined;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
process = this.statusManager.updateProcess(step, process.type, 'ACTION_REQUIRED');
|
|
312
|
-
txHash = await getAction(this.client, sendTransaction, 'sendTransaction')({
|
|
313
|
-
to: transactionRequest.to,
|
|
314
|
-
account: this.client.account,
|
|
315
|
-
data: transactionRequest.data,
|
|
316
|
-
value: transactionRequest.value,
|
|
317
|
-
gas: transactionRequest.gas,
|
|
318
|
-
gasPrice: transactionRequest.gasPrice,
|
|
319
|
-
maxFeePerGas: transactionRequest.maxFeePerGas,
|
|
320
|
-
maxPriorityFeePerGas: transactionRequest.maxPriorityFeePerGas,
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
process = this.statusManager.updateProcess(step, process.type, 'PENDING',
|
|
325
|
-
// When atomic batch is supported, txHash represents the batch hash rather than an individual transaction hash at this point
|
|
326
|
-
atomicBatchSupported
|
|
327
|
-
? {
|
|
328
|
-
atomicBatchSupported,
|
|
329
|
-
}
|
|
330
|
-
: isTransactionRelayed
|
|
331
|
-
? undefined
|
|
332
|
-
: {
|
|
333
|
-
txHash: txHash,
|
|
334
|
-
txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${txHash}`,
|
|
335
|
-
});
|
|
336
252
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
transactionReceipt = await waitForBatchTransactionReceipt(this.client, txHash);
|
|
253
|
+
else {
|
|
254
|
+
updatedStep = await getStepTransaction(stepBase);
|
|
340
255
|
}
|
|
341
|
-
|
|
342
|
-
|
|
256
|
+
const comparedStep = await stepComparison(this.statusManager, step, updatedStep, this.allowUserInteraction, this.executionOptions);
|
|
257
|
+
Object.assign(step, {
|
|
258
|
+
...comparedStep,
|
|
259
|
+
execution: step.execution,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
if (!step.transactionRequest) {
|
|
263
|
+
throw new TransactionError(LiFiErrorCode.TransactionUnprepared, 'Unable to prepare transaction.');
|
|
264
|
+
}
|
|
265
|
+
let transactionRequest = {
|
|
266
|
+
to: step.transactionRequest.to,
|
|
267
|
+
from: step.transactionRequest.from,
|
|
268
|
+
data: step.transactionRequest.data,
|
|
269
|
+
value: step.transactionRequest.value
|
|
270
|
+
? BigInt(step.transactionRequest.value)
|
|
271
|
+
: undefined,
|
|
272
|
+
gas: step.transactionRequest.gasLimit
|
|
273
|
+
? BigInt(step.transactionRequest.gasLimit)
|
|
274
|
+
: undefined,
|
|
275
|
+
// gasPrice: step.transactionRequest.gasPrice
|
|
276
|
+
// ? BigInt(step.transactionRequest.gasPrice as string)
|
|
277
|
+
// : undefined,
|
|
278
|
+
// maxFeePerGas: step.transactionRequest.maxFeePerGas
|
|
279
|
+
// ? BigInt(step.transactionRequest.maxFeePerGas as string)
|
|
280
|
+
// : undefined,
|
|
281
|
+
maxPriorityFeePerGas: this.client.account?.type === 'local'
|
|
282
|
+
? await getMaxPriorityFeePerGas(this.client)
|
|
283
|
+
: step.transactionRequest.maxPriorityFeePerGas
|
|
284
|
+
? BigInt(step.transactionRequest.maxPriorityFeePerGas)
|
|
285
|
+
: undefined,
|
|
286
|
+
};
|
|
287
|
+
if (this.executionOptions?.updateTransactionRequestHook) {
|
|
288
|
+
const customizedTransactionRequest = await this.executionOptions.updateTransactionRequestHook({
|
|
289
|
+
requestType: 'transaction',
|
|
290
|
+
...transactionRequest,
|
|
291
|
+
});
|
|
292
|
+
transactionRequest = {
|
|
293
|
+
...transactionRequest,
|
|
294
|
+
...customizedTransactionRequest,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
// Make sure that the chain is still correct
|
|
298
|
+
const updatedClient = await this.checkClient(step, process);
|
|
299
|
+
if (!updatedClient) {
|
|
300
|
+
return step;
|
|
301
|
+
}
|
|
302
|
+
process = this.statusManager.updateProcess(step, process.type, 'ACTION_REQUIRED');
|
|
303
|
+
if (!this.allowUserInteraction) {
|
|
304
|
+
return step;
|
|
305
|
+
}
|
|
306
|
+
let txHash;
|
|
307
|
+
let isTransactionRelayed = false;
|
|
308
|
+
if (atomicBatchSupported) {
|
|
309
|
+
const transferCall = {
|
|
310
|
+
chainId: fromChain.id,
|
|
311
|
+
data: transactionRequest.data,
|
|
312
|
+
to: transactionRequest.to,
|
|
313
|
+
value: transactionRequest.value,
|
|
314
|
+
};
|
|
315
|
+
calls.push(transferCall);
|
|
316
|
+
txHash = (await getAction(this.client, sendCalls, 'sendCalls')({
|
|
317
|
+
account: this.client.account,
|
|
318
|
+
calls,
|
|
319
|
+
}));
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
let permitSignature;
|
|
323
|
+
if (permitSupported) {
|
|
324
|
+
permitSignature = await signPermitMessage(this.client, {
|
|
325
|
+
transactionRequest,
|
|
326
|
+
chain: fromChain,
|
|
327
|
+
tokenAddress: step.action.fromToken.address,
|
|
328
|
+
amount: BigInt(step.action.fromAmount),
|
|
329
|
+
nativePermit,
|
|
330
|
+
permitData: isRelayerTransaction ? step.permitData : undefined,
|
|
331
|
+
useWitness: isRelayerTransaction,
|
|
332
|
+
});
|
|
333
|
+
transactionRequest.to = fromChain.permit2Proxy;
|
|
334
|
+
this.statusManager.updateProcess(step, process.type, 'DONE');
|
|
343
335
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
336
|
+
if (isRelayerTransaction && permitSignature) {
|
|
337
|
+
process = this.statusManager.findOrCreateProcess({
|
|
338
|
+
step,
|
|
339
|
+
type: currentProcessType,
|
|
340
|
+
status: 'PENDING',
|
|
341
|
+
});
|
|
342
|
+
const relayedTransaction = await relayTransaction({
|
|
343
|
+
tokenOwner: this.client.account.address,
|
|
347
344
|
chainId: fromChain.id,
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
|
|
353
|
-
});
|
|
354
|
-
},
|
|
345
|
+
permit: step.permit,
|
|
346
|
+
witness: step.witness,
|
|
347
|
+
signedPermitData: permitSignature.signature,
|
|
348
|
+
callData: transactionRequest.data,
|
|
355
349
|
});
|
|
350
|
+
txHash = relayedTransaction.data.taskId;
|
|
351
|
+
isTransactionRelayed = true;
|
|
356
352
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
353
|
+
else {
|
|
354
|
+
process = this.statusManager.findOrCreateProcess({
|
|
355
|
+
step,
|
|
356
|
+
type: currentProcessType,
|
|
357
|
+
status: 'STARTED',
|
|
358
|
+
});
|
|
359
|
+
if (permitSignature) {
|
|
360
|
+
// If we have a permit signature, we need to use updated data
|
|
361
|
+
transactionRequest.data = permitSignature.data;
|
|
362
|
+
try {
|
|
363
|
+
// Try to re-estimate the gas due to additional Permit data
|
|
364
|
+
const estimatedGas = await estimateGas(this.client, {
|
|
365
|
+
account: this.client.account,
|
|
366
|
+
to: transactionRequest.to,
|
|
367
|
+
data: transactionRequest.data,
|
|
368
|
+
value: transactionRequest.value,
|
|
369
|
+
});
|
|
370
|
+
transactionRequest.gas =
|
|
371
|
+
transactionRequest.gas && transactionRequest.gas > estimatedGas
|
|
372
|
+
? transactionRequest.gas
|
|
373
|
+
: estimatedGas;
|
|
374
|
+
}
|
|
375
|
+
catch {
|
|
376
|
+
// Let the wallet estimate the gas in case of failure
|
|
377
|
+
transactionRequest.gas = undefined;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
process = this.statusManager.updateProcess(step, process.type, 'ACTION_REQUIRED');
|
|
381
|
+
txHash = await getAction(this.client, sendTransaction, 'sendTransaction')({
|
|
382
|
+
to: transactionRequest.to,
|
|
383
|
+
account: this.client.account,
|
|
384
|
+
data: transactionRequest.data,
|
|
385
|
+
value: transactionRequest.value,
|
|
386
|
+
gas: transactionRequest.gas,
|
|
387
|
+
gasPrice: transactionRequest.gasPrice,
|
|
388
|
+
maxFeePerGas: transactionRequest.maxFeePerGas,
|
|
389
|
+
maxPriorityFeePerGas: transactionRequest.maxPriorityFeePerGas,
|
|
390
|
+
chain: convertExtendedChain(fromChain),
|
|
364
391
|
});
|
|
365
|
-
}
|
|
366
|
-
if (isBridgeExecution) {
|
|
367
|
-
process = this.statusManager.updateProcess(step, process.type, 'DONE');
|
|
368
392
|
}
|
|
369
393
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
const transactionHash = process.txHash;
|
|
384
|
-
if (!transactionHash) {
|
|
385
|
-
throw new Error('Transaction hash is undefined.');
|
|
386
|
-
}
|
|
387
|
-
if (isBridgeExecution) {
|
|
388
|
-
process = this.statusManager.findOrCreateProcess({
|
|
394
|
+
process = this.statusManager.updateProcess(step, process.type, 'PENDING',
|
|
395
|
+
// When atomic batch is supported, txHash represents the batch hash rather than an individual transaction hash at this point
|
|
396
|
+
atomicBatchSupported
|
|
397
|
+
? {
|
|
398
|
+
atomicBatchSupported,
|
|
399
|
+
}
|
|
400
|
+
: isTransactionRelayed
|
|
401
|
+
? undefined
|
|
402
|
+
: {
|
|
403
|
+
txHash: txHash,
|
|
404
|
+
txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${txHash}`,
|
|
405
|
+
});
|
|
406
|
+
await this.waitForTransaction({
|
|
389
407
|
step,
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
408
|
+
process,
|
|
409
|
+
fromChain,
|
|
410
|
+
toChain,
|
|
411
|
+
atomicBatchSupported,
|
|
412
|
+
isRelayerTransaction,
|
|
413
|
+
txHash,
|
|
414
|
+
isBridgeExecution,
|
|
393
415
|
});
|
|
416
|
+
// DONE
|
|
417
|
+
return step;
|
|
418
|
+
}
|
|
419
|
+
catch (e) {
|
|
420
|
+
const error = await parseEVMErrors(e, step, process);
|
|
421
|
+
process = this.statusManager.updateProcess(step, process?.type || currentProcessType, 'FAILED', {
|
|
422
|
+
error: {
|
|
423
|
+
message: error.cause.message,
|
|
424
|
+
code: error.code,
|
|
425
|
+
},
|
|
426
|
+
});
|
|
427
|
+
this.statusManager.updateExecution(step, 'FAILED');
|
|
428
|
+
throw error;
|
|
394
429
|
}
|
|
395
|
-
await waitForDestinationChainTransaction(step, process.type, transactionHash, toChain, this.statusManager);
|
|
396
|
-
// DONE
|
|
397
|
-
return step;
|
|
398
430
|
}
|
|
399
431
|
});
|
|
400
432
|
this.client = options.client;
|