@lifi/sdk 3.5.0-beta.0 → 3.5.1-beta.0

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 (183) hide show
  1. package/package.json +8 -9
  2. package/src/_cjs/constants.js +2 -4
  3. package/src/_cjs/constants.js.map +1 -1
  4. package/src/_cjs/core/EVM/EVM.js +4 -0
  5. package/src/_cjs/core/EVM/EVM.js.map +1 -1
  6. package/src/_cjs/core/EVM/EVMStepExecutor.js +79 -145
  7. package/src/_cjs/core/EVM/EVMStepExecutor.js.map +1 -1
  8. package/src/_cjs/core/EVM/abi.js +43 -36
  9. package/src/_cjs/core/EVM/abi.js.map +1 -1
  10. package/src/_cjs/core/EVM/checkAllowance.js +30 -36
  11. package/src/_cjs/core/EVM/checkAllowance.js.map +1 -1
  12. package/src/_cjs/core/EVM/getAllowance.js.map +1 -1
  13. package/src/_cjs/core/EVM/getEVMBalance.js.map +1 -1
  14. package/src/_cjs/core/EVM/multisig.js +29 -0
  15. package/src/_cjs/core/EVM/multisig.js.map +1 -0
  16. package/src/_cjs/core/EVM/parseEVMErrors.js +0 -3
  17. package/src/_cjs/core/EVM/parseEVMErrors.js.map +1 -1
  18. package/src/_cjs/core/EVM/setAllowance.js +6 -4
  19. package/src/_cjs/core/EVM/setAllowance.js.map +1 -1
  20. package/src/_cjs/core/EVM/switchChain.js +3 -2
  21. package/src/_cjs/core/EVM/switchChain.js.map +1 -1
  22. package/src/_cjs/core/EVM/types.js.map +1 -1
  23. package/src/_cjs/core/EVM/utils.js +1 -2
  24. package/src/_cjs/core/EVM/utils.js.map +1 -1
  25. package/src/_cjs/core/Solana/SolanaStepExecutor.js +2 -48
  26. package/src/_cjs/core/Solana/SolanaStepExecutor.js.map +1 -1
  27. package/src/_cjs/core/UTXO/UTXOStepExecutor.js +2 -48
  28. package/src/_cjs/core/UTXO/UTXOStepExecutor.js.map +1 -1
  29. package/src/_cjs/core/checkBalance.js +3 -3
  30. package/src/_cjs/core/checkBalance.js.map +1 -1
  31. package/src/_cjs/core/waitForDestinationChainTransaction.js +53 -0
  32. package/src/_cjs/core/waitForDestinationChainTransaction.js.map +1 -0
  33. package/src/_cjs/core/{waitForReceivingTransaction.js → waitForTransactionStatus.js} +3 -3
  34. package/src/_cjs/core/waitForTransactionStatus.js.map +1 -0
  35. package/src/_cjs/index.js.map +1 -1
  36. package/src/_cjs/version.js +1 -1
  37. package/src/_esm/constants.js +1 -3
  38. package/src/_esm/constants.js.map +1 -1
  39. package/src/_esm/core/EVM/EVM.js +4 -0
  40. package/src/_esm/core/EVM/EVM.js.map +1 -1
  41. package/src/_esm/core/EVM/EVMStepExecutor.js +92 -179
  42. package/src/_esm/core/EVM/EVMStepExecutor.js.map +1 -1
  43. package/src/_esm/core/EVM/abi.js +42 -37
  44. package/src/_esm/core/EVM/abi.js.map +1 -1
  45. package/src/_esm/core/EVM/checkAllowance.js +32 -41
  46. package/src/_esm/core/EVM/checkAllowance.js.map +1 -1
  47. package/src/_esm/core/EVM/getAllowance.js.map +1 -1
  48. package/src/_esm/core/EVM/getEVMBalance.js.map +1 -1
  49. package/src/_esm/core/EVM/multisig.js +25 -0
  50. package/src/_esm/core/EVM/multisig.js.map +1 -0
  51. package/src/_esm/core/EVM/parseEVMErrors.js +0 -8
  52. package/src/_esm/core/EVM/parseEVMErrors.js.map +1 -1
  53. package/src/_esm/core/EVM/setAllowance.js +6 -4
  54. package/src/_esm/core/EVM/setAllowance.js.map +1 -1
  55. package/src/_esm/core/EVM/switchChain.js +3 -2
  56. package/src/_esm/core/EVM/switchChain.js.map +1 -1
  57. package/src/_esm/core/EVM/types.js.map +1 -1
  58. package/src/_esm/core/EVM/utils.js +1 -2
  59. package/src/_esm/core/EVM/utils.js.map +1 -1
  60. package/src/_esm/core/Solana/SolanaStepExecutor.js +3 -50
  61. package/src/_esm/core/Solana/SolanaStepExecutor.js.map +1 -1
  62. package/src/_esm/core/UTXO/UTXOStepExecutor.js +4 -51
  63. package/src/_esm/core/UTXO/UTXOStepExecutor.js.map +1 -1
  64. package/src/_esm/core/checkBalance.js +3 -3
  65. package/src/_esm/core/checkBalance.js.map +1 -1
  66. package/src/_esm/core/waitForDestinationChainTransaction.js +52 -0
  67. package/src/_esm/core/waitForDestinationChainTransaction.js.map +1 -0
  68. package/src/_esm/core/{waitForReceivingTransaction.js → waitForTransactionStatus.js} +2 -2
  69. package/src/_esm/core/waitForTransactionStatus.js.map +1 -0
  70. package/src/_esm/index.js.map +1 -1
  71. package/src/_esm/version.js +1 -1
  72. package/src/_types/constants.d.ts +1 -3
  73. package/src/_types/constants.d.ts.map +1 -1
  74. package/src/_types/core/EVM/EVM.d.ts.map +1 -1
  75. package/src/_types/core/EVM/EVMStepExecutor.d.ts +4 -7
  76. package/src/_types/core/EVM/EVMStepExecutor.d.ts.map +1 -1
  77. package/src/_types/core/EVM/abi.d.ts +5 -202
  78. package/src/_types/core/EVM/abi.d.ts.map +1 -1
  79. package/src/_types/core/EVM/checkAllowance.d.ts +2 -12
  80. package/src/_types/core/EVM/checkAllowance.d.ts.map +1 -1
  81. package/src/_types/core/EVM/getAllowance.d.ts +4 -5
  82. package/src/_types/core/EVM/getAllowance.d.ts.map +1 -1
  83. package/src/_types/core/EVM/getEVMBalance.d.ts +1 -2
  84. package/src/_types/core/EVM/getEVMBalance.d.ts.map +1 -1
  85. package/src/_types/core/EVM/multisig.d.ts +6 -0
  86. package/src/_types/core/EVM/multisig.d.ts.map +1 -0
  87. package/src/_types/core/EVM/setAllowance.d.ts +2 -2
  88. package/src/_types/core/EVM/setAllowance.d.ts.map +1 -1
  89. package/src/_types/core/EVM/switchChain.d.ts.map +1 -1
  90. package/src/_types/core/EVM/types.d.ts +18 -1
  91. package/src/_types/core/EVM/types.d.ts.map +1 -1
  92. package/src/_types/core/EVM/utils.d.ts +2 -2
  93. package/src/_types/core/EVM/utils.d.ts.map +1 -1
  94. package/src/_types/core/Solana/SolanaStepExecutor.d.ts.map +1 -1
  95. package/src/_types/core/UTXO/UTXOStepExecutor.d.ts.map +1 -1
  96. package/src/_types/core/checkBalance.d.ts.map +1 -1
  97. package/src/_types/core/waitForDestinationChainTransaction.d.ts +5 -0
  98. package/src/_types/core/waitForDestinationChainTransaction.d.ts.map +1 -0
  99. package/src/_types/core/waitForTransactionStatus.d.ts +4 -0
  100. package/src/_types/core/waitForTransactionStatus.d.ts.map +1 -0
  101. package/src/_types/index.d.ts +1 -1
  102. package/src/_types/index.d.ts.map +1 -1
  103. package/src/_types/version.d.ts +1 -1
  104. package/src/constants.ts +1 -6
  105. package/src/core/EVM/EVM.ts +4 -0
  106. package/src/core/EVM/EVMStepExecutor.ts +156 -245
  107. package/src/core/EVM/abi.ts +43 -40
  108. package/src/core/EVM/checkAllowance.ts +92 -96
  109. package/src/core/EVM/getAllowance.ts +8 -8
  110. package/src/core/EVM/getEVMBalance.ts +2 -2
  111. package/src/core/EVM/multisig.ts +54 -0
  112. package/src/core/EVM/parseEVMErrors.ts +0 -8
  113. package/src/core/EVM/setAllowance.ts +21 -15
  114. package/src/core/EVM/switchChain.ts +12 -3
  115. package/src/core/EVM/types.ts +27 -1
  116. package/src/core/EVM/utils.ts +3 -4
  117. package/src/core/Solana/SolanaStepExecutor.ts +9 -63
  118. package/src/core/UTXO/UTXOStepExecutor.ts +10 -68
  119. package/src/core/checkBalance.ts +3 -6
  120. package/src/core/waitForDestinationChainTransaction.ts +79 -0
  121. package/src/core/{waitForReceivingTransaction.ts → waitForTransactionStatus.ts} +1 -1
  122. package/src/index.ts +3 -0
  123. package/src/version.ts +1 -1
  124. package/src/_cjs/core/EVM/getNativePermit.js +0 -90
  125. package/src/_cjs/core/EVM/getNativePermit.js.map +0 -1
  126. package/src/_cjs/core/EVM/permit2/allowanceTransfer.js +0 -100
  127. package/src/_cjs/core/EVM/permit2/allowanceTransfer.js.map +0 -1
  128. package/src/_cjs/core/EVM/permit2/constants.js +0 -12
  129. package/src/_cjs/core/EVM/permit2/constants.js.map +0 -1
  130. package/src/_cjs/core/EVM/permit2/domain.js +0 -12
  131. package/src/_cjs/core/EVM/permit2/domain.js.map +0 -1
  132. package/src/_cjs/core/EVM/permit2/signatureTransfer.js +0 -121
  133. package/src/_cjs/core/EVM/permit2/signatureTransfer.js.map +0 -1
  134. package/src/_cjs/core/EVM/signPermitMessage.js +0 -168
  135. package/src/_cjs/core/EVM/signPermitMessage.js.map +0 -1
  136. package/src/_cjs/core/EVM/waitForBatchTransactionReceipt.js +0 -29
  137. package/src/_cjs/core/EVM/waitForBatchTransactionReceipt.js.map +0 -1
  138. package/src/_cjs/core/waitForReceivingTransaction.js.map +0 -1
  139. package/src/_cjs/utils/invariant.js +0 -17
  140. package/src/_cjs/utils/invariant.js.map +0 -1
  141. package/src/_esm/core/EVM/getNativePermit.js +0 -95
  142. package/src/_esm/core/EVM/getNativePermit.js.map +0 -1
  143. package/src/_esm/core/EVM/permit2/allowanceTransfer.js +0 -93
  144. package/src/_esm/core/EVM/permit2/allowanceTransfer.js.map +0 -1
  145. package/src/_esm/core/EVM/permit2/constants.js +0 -9
  146. package/src/_esm/core/EVM/permit2/constants.js.map +0 -1
  147. package/src/_esm/core/EVM/permit2/domain.js +0 -9
  148. package/src/_esm/core/EVM/permit2/domain.js.map +0 -1
  149. package/src/_esm/core/EVM/permit2/signatureTransfer.js +0 -117
  150. package/src/_esm/core/EVM/permit2/signatureTransfer.js.map +0 -1
  151. package/src/_esm/core/EVM/signPermitMessage.js +0 -162
  152. package/src/_esm/core/EVM/signPermitMessage.js.map +0 -1
  153. package/src/_esm/core/EVM/waitForBatchTransactionReceipt.js +0 -25
  154. package/src/_esm/core/EVM/waitForBatchTransactionReceipt.js.map +0 -1
  155. package/src/_esm/core/waitForReceivingTransaction.js.map +0 -1
  156. package/src/_esm/utils/invariant.js +0 -43
  157. package/src/_esm/utils/invariant.js.map +0 -1
  158. package/src/_types/core/EVM/getNativePermit.d.ts +0 -18
  159. package/src/_types/core/EVM/getNativePermit.d.ts.map +0 -1
  160. package/src/_types/core/EVM/permit2/allowanceTransfer.d.ts +0 -41
  161. package/src/_types/core/EVM/permit2/allowanceTransfer.d.ts.map +0 -1
  162. package/src/_types/core/EVM/permit2/constants.d.ts +0 -8
  163. package/src/_types/core/EVM/permit2/constants.d.ts.map +0 -1
  164. package/src/_types/core/EVM/permit2/domain.d.ts +0 -8
  165. package/src/_types/core/EVM/permit2/domain.d.ts.map +0 -1
  166. package/src/_types/core/EVM/permit2/signatureTransfer.d.ts +0 -42
  167. package/src/_types/core/EVM/permit2/signatureTransfer.d.ts.map +0 -1
  168. package/src/_types/core/EVM/signPermitMessage.d.ts +0 -22
  169. package/src/_types/core/EVM/signPermitMessage.d.ts.map +0 -1
  170. package/src/_types/core/EVM/waitForBatchTransactionReceipt.d.ts +0 -4
  171. package/src/_types/core/EVM/waitForBatchTransactionReceipt.d.ts.map +0 -1
  172. package/src/_types/core/waitForReceivingTransaction.d.ts +0 -4
  173. package/src/_types/core/waitForReceivingTransaction.d.ts.map +0 -1
  174. package/src/_types/utils/invariant.d.ts +0 -22
  175. package/src/_types/utils/invariant.d.ts.map +0 -1
  176. package/src/core/EVM/getNativePermit.ts +0 -113
  177. package/src/core/EVM/permit2/allowanceTransfer.ts +0 -168
  178. package/src/core/EVM/permit2/constants.ts +0 -11
  179. package/src/core/EVM/permit2/domain.ts +0 -20
  180. package/src/core/EVM/permit2/signatureTransfer.ts +0 -214
  181. package/src/core/EVM/signPermitMessage.ts +0 -248
  182. package/src/core/EVM/waitForBatchTransactionReceipt.ts +0 -49
  183. package/src/utils/invariant.ts +0 -51
@@ -1,67 +1,54 @@
1
+ import type { Process } from '@lifi/types'
1
2
  import type {
2
- ExtendedTransactionInfo,
3
- FullStatusData,
4
- Process,
5
- } from '@lifi/types'
6
- import type {
7
- Address,
8
3
  Client,
4
+ GetAddressesReturnType,
9
5
  Hash,
10
- Hex,
11
6
  SendTransactionParameters,
12
- TransactionReceipt,
13
7
  } from 'viem'
14
- import { estimateGas, getAddresses, sendTransaction } from 'viem/actions'
15
- import { getCapabilities, sendCalls } from 'viem/experimental'
8
+ import { getAddresses, sendTransaction } from 'viem/actions'
9
+ import { getAction } from 'viem/utils'
16
10
  import { config } from '../../config.js'
17
11
  import { LiFiErrorCode } from '../../errors/constants.js'
18
- import { TransactionError } from '../../errors/errors.js'
12
+ import { TransactionError, ValidationError } from '../../errors/errors.js'
19
13
  import { getStepTransaction } from '../../services/api.js'
20
- import { getTransactionFailedMessage } from '../../utils/getTransactionMessage.js'
21
14
  import { isZeroAddress } from '../../utils/isZeroAddress.js'
22
15
  import { BaseStepExecutor } from '../BaseStepExecutor.js'
23
16
  import { checkBalance } from '../checkBalance.js'
24
- import { getSubstatusMessage } from '../processMessages.js'
25
17
  import { stepComparison } from '../stepComparison.js'
26
18
  import type {
27
19
  LiFiStepExtended,
28
20
  StepExecutorOptions,
29
21
  TransactionParameters,
30
22
  } from '../types.js'
31
- import { waitForReceivingTransaction } from '../waitForReceivingTransaction.js'
23
+ import { waitForDestinationChainTransaction } from '../waitForDestinationChainTransaction.js'
32
24
  import { checkAllowance } from './checkAllowance.js'
33
- import { getNativePermit } from './getNativePermit.js'
25
+ import { updateMultisigRouteProcess } from './multisig.js'
34
26
  import { parseEVMErrors } from './parseEVMErrors.js'
35
- import { signPermitMessage } from './signPermitMessage.js'
36
27
  import { switchChain } from './switchChain.js'
28
+ import type { MultisigConfig, MultisigTransaction } from './types.js'
37
29
  import { getMaxPriorityFeePerGas } from './utils.js'
38
- import {
39
- type WalletCallReceipt,
40
- waitForBatchTransactionReceipt,
41
- } from './waitForBatchTransactionReceipt.js'
42
30
  import { waitForTransactionReceipt } from './waitForTransactionReceipt.js'
43
31
 
44
- export type Call = {
45
- data?: Hex
46
- to?: Address
47
- value?: bigint
48
- chainId?: number
49
- }
50
-
51
32
  export interface EVMStepExecutorOptions extends StepExecutorOptions {
52
33
  client: Client
34
+ multisig?: MultisigConfig
53
35
  }
54
36
 
55
37
  export class EVMStepExecutor extends BaseStepExecutor {
56
38
  private client: Client
39
+ private multisig?: MultisigConfig
57
40
 
58
41
  constructor(options: EVMStepExecutorOptions) {
59
42
  super(options)
60
43
  this.client = options.client
44
+ this.multisig = options.multisig
61
45
  }
62
46
 
63
47
  // Ensure that we are using the right chain and wallet when executing transactions.
64
- checkClient = async (step: LiFiStepExtended, process?: Process) => {
48
+ checkClient = async (
49
+ step: LiFiStepExtended,
50
+ process?: Process
51
+ ): Promise<Client | undefined> => {
65
52
  const updatedClient = await switchChain(
66
53
  this.client,
67
54
  this.statusManager,
@@ -76,7 +63,11 @@ export class EVMStepExecutor extends BaseStepExecutor {
76
63
  // Prevent execution of the quote by wallet different from the one which requested the quote
77
64
  let accountAddress = this.client.account?.address
78
65
  if (!accountAddress) {
79
- const accountAddresses = await getAddresses(this.client)
66
+ const accountAddresses = (await getAction(
67
+ this.client,
68
+ getAddresses,
69
+ 'getAddresses'
70
+ )(undefined)) as GetAddressesReturnType
80
71
  accountAddress = accountAddresses?.[0]
81
72
  }
82
73
  if (accountAddress !== step.action.fromAddress) {
@@ -112,101 +103,68 @@ export class EVMStepExecutor extends BaseStepExecutor {
112
103
  executeStep = async (step: LiFiStepExtended): Promise<LiFiStepExtended> => {
113
104
  step.execution = this.statusManager.initExecutionObject(step)
114
105
 
115
- // Find if it's bridging and the step is waiting for a transaction on the receiving chain
116
- const recievingChainProcess = step.execution?.process.find(
106
+ // Find if it's bridging and the step is waiting for a transaction on the destination chain
107
+ const destinationChainProcess = step.execution?.process.find(
117
108
  (process) => process.type === 'RECEIVING_CHAIN'
118
109
  )
119
110
 
120
111
  // Make sure that the chain is still correct
121
- // If the step is waiting for a transaction on the receiving chain, we do not switch the chain
112
+ // If the step is waiting for a transaction on the destination chain, we do not switch the chain
122
113
  // All changes are already done from the source chain
123
114
  // Return the step
124
- if (recievingChainProcess?.substatus !== 'WAIT_DESTINATION_TRANSACTION') {
115
+ if (destinationChainProcess?.substatus !== 'WAIT_DESTINATION_TRANSACTION') {
125
116
  const updatedClient = await this.checkClient(step)
126
117
  if (!updatedClient) {
127
118
  return step
128
119
  }
129
120
  }
130
121
 
131
- const fromChain = await config.getChainById(step.action.fromChainId)
132
- const toChain = await config.getChainById(step.action.toChainId)
122
+ const isMultisigClient = !!this.multisig?.isMultisigWalletClient
123
+ const multisigBatchTransactions: MultisigTransaction[] = []
133
124
 
134
- let atomicBatchSupported = false
135
- try {
136
- const capabilities = await getCapabilities(this.client)
137
- atomicBatchSupported = capabilities[fromChain.id]?.atomicBatch?.supported
138
- } catch {
139
- // If the wallet does not support getCapabilities, we assume that atomic batch is not supported
140
- }
125
+ const shouldBatchTransactions =
126
+ this.multisig?.shouldBatchTransactions &&
127
+ !!this.multisig.sendBatchTransaction
141
128
 
142
- const calls: Call[] = []
129
+ const fromChain = await config.getChainById(step.action.fromChainId)
130
+ const toChain = await config.getChainById(step.action.toChainId)
143
131
 
144
132
  const isBridgeExecution = fromChain.id !== toChain.id
145
133
  const currentProcessType = isBridgeExecution ? 'CROSS_CHAIN' : 'SWAP'
146
134
 
147
- // STEP 1: Check allowance
148
- // Find existing swap/bridge process
135
+ // Check allowance
149
136
  const existingProcess = step.execution.process.find(
150
137
  (p) => p.type === currentProcessType
151
138
  )
152
139
 
153
- // Check if token requires approval
154
- // Native tokens (like ETH) don't need approval since they're not ERC20 tokens
155
- // We should support different permit types:
156
- // 1. Native permits (EIP-2612)
157
- // 2. Permit2 - Universal permit implementation by Uniswap (limited to certain chains)
158
- // 3. Standard ERC20 approval
159
- const nativePermit = await getNativePermit(
160
- this.client,
161
- fromChain,
162
- step.action.fromToken.address as Address
163
- )
164
- // Check if proxy contract is available and token supports native permits, not available for atomic batch
165
- const nativePermitSupported =
166
- !!fromChain.permit2Proxy &&
167
- nativePermit.supported &&
168
- !atomicBatchSupported
169
- // Check if chain has Permit2 contract deployed. Permit2 should not be available for atomic batch.
170
- const permit2Supported =
171
- !!fromChain.permit2 && !!fromChain.permit2Proxy && !atomicBatchSupported
172
- // Token supports either native permits or Permit2
173
- const permitSupported = permit2Supported || nativePermitSupported
174
-
140
+ // Check token approval only if fromToken is not the native token => no approval needed in that case
175
141
  const checkForAllowance =
176
- // No existing swap/bridgetransaction is pending
177
142
  !existingProcess?.txHash &&
178
- // Token is not native (address is not zero)
179
143
  !isZeroAddress(step.action.fromToken.address) &&
180
- // Token doesn't support native permits
181
- !nativePermitSupported
144
+ (shouldBatchTransactions || !isMultisigClient)
182
145
 
183
146
  if (checkForAllowance) {
184
- // Check if token needs approval and get approval transaction or message data when available
185
- const data = await checkAllowance({
186
- client: this.client,
187
- chain: fromChain,
147
+ const data = await checkAllowance(
148
+ this.client,
149
+ fromChain,
188
150
  step,
189
- statusManager: this.statusManager,
190
- executionOptions: this.executionOptions,
191
- allowUserInteraction: this.allowUserInteraction,
192
- atomicBatchSupported,
193
- permit2Supported,
194
- })
151
+ this.statusManager,
152
+ this.executionOptions,
153
+ this.allowUserInteraction,
154
+ shouldBatchTransactions
155
+ )
195
156
 
196
157
  if (data) {
197
- // Create approval transaction call
198
- // No value needed since we're only approving ERC20 tokens
199
- if (atomicBatchSupported) {
200
- calls.push({
201
- chainId: step.action.fromToken.chainId,
202
- to: step.action.fromToken.address as Address,
203
- data,
204
- })
158
+ // allowance doesn't need value
159
+ const baseTransaction: MultisigTransaction = {
160
+ to: step.action.fromToken.address,
161
+ data,
205
162
  }
163
+
164
+ multisigBatchTransactions.push(baseTransaction)
206
165
  }
207
166
  }
208
167
 
209
- // STEP 2: Get transaction
210
168
  let process = this.statusManager.findOrCreateProcess({
211
169
  step,
212
170
  type: currentProcessType,
@@ -214,7 +172,28 @@ export class EVMStepExecutor extends BaseStepExecutor {
214
172
  })
215
173
 
216
174
  if (process.status !== 'DONE') {
175
+ const multisigProcess = step.execution.process.find(
176
+ (p) => !!p.multisigTxHash
177
+ )
178
+
217
179
  try {
180
+ if (isMultisigClient && multisigProcess) {
181
+ const multisigTxHash = multisigProcess.multisigTxHash as Hash
182
+ if (!multisigTxHash) {
183
+ throw new ValidationError(
184
+ 'Multisig internal transaction hash is undefined.'
185
+ )
186
+ }
187
+ await updateMultisigRouteProcess(
188
+ multisigTxHash,
189
+ step,
190
+ process.type,
191
+ fromChain,
192
+ this.statusManager,
193
+ this.multisig
194
+ )
195
+ }
196
+
218
197
  let txHash: Hash
219
198
  if (process.txHash) {
220
199
  // Make sure that the chain is still correct
@@ -235,7 +214,7 @@ export class EVMStepExecutor extends BaseStepExecutor {
235
214
  // Check balance
236
215
  await checkBalance(this.client.account!.address, step)
237
216
 
238
- // Create new transaction request
217
+ // Create new transaction
239
218
  if (!step.transactionRequest) {
240
219
  const { execution, ...stepBase } = step
241
220
  const updatedStep = await getStepTransaction(stepBase)
@@ -259,6 +238,22 @@ export class EVMStepExecutor extends BaseStepExecutor {
259
238
  )
260
239
  }
261
240
 
241
+ // Make sure that the chain is still correct
242
+ const updatedClient = await this.checkClient(step, process)
243
+ if (!updatedClient) {
244
+ return step
245
+ }
246
+
247
+ process = this.statusManager.updateProcess(
248
+ step,
249
+ process.type,
250
+ 'ACTION_REQUIRED'
251
+ )
252
+
253
+ if (!this.allowUserInteraction) {
254
+ return step
255
+ }
256
+
262
257
  let transactionRequest: TransactionParameters = {
263
258
  to: step.transactionRequest.to,
264
259
  from: step.transactionRequest.from,
@@ -296,72 +291,30 @@ export class EVMStepExecutor extends BaseStepExecutor {
296
291
  }
297
292
  }
298
293
 
299
- // STEP 3: Send the transaction
300
- // Make sure that the chain is still correct
301
- const updatedClient = await this.checkClient(step, process)
302
- if (!updatedClient) {
303
- return step
304
- }
305
-
306
- process = this.statusManager.updateProcess(
307
- step,
308
- process.type,
309
- permitSupported ? 'PERMIT_REQUIRED' : 'ACTION_REQUIRED'
310
- )
311
-
312
- if (!this.allowUserInteraction) {
313
- return step
314
- }
315
-
316
- if (atomicBatchSupported) {
317
- const transferCall: Call = {
318
- chainId: fromChain.id,
319
- data: transactionRequest.data as Hex,
320
- to: transactionRequest.to as Address,
321
- value: transactionRequest.value,
322
- }
323
-
324
- calls.push(transferCall)
325
-
326
- txHash = (await sendCalls(this.client, {
327
- account: this.client.account!,
328
- calls,
329
- })) as Address
330
- } else {
331
- if (permitSupported) {
332
- const { data } = await signPermitMessage(
333
- this.client,
334
- transactionRequest,
335
- fromChain,
336
- step.action.fromToken.address as Address,
337
- BigInt(step.action.fromAmount),
338
- nativePermit
339
- )
340
-
341
- transactionRequest.to = fromChain.permit2Proxy
342
- transactionRequest.data = data
343
-
344
- try {
345
- // Try to re-estimate the gas due to additional Permit data
346
- transactionRequest.gas = await estimateGas(this.client, {
347
- account: this.client.account!,
348
- to: transactionRequest.to as Address,
349
- data: transactionRequest.data as Hex,
350
- value: transactionRequest.value,
351
- })
352
- } catch {
353
- // Let the wallet estimate the gas in case of failure
354
- transactionRequest.gas = undefined
294
+ if (shouldBatchTransactions && this.multisig?.sendBatchTransaction) {
295
+ if (transactionRequest.to && transactionRequest.data) {
296
+ const populatedTransaction: MultisigTransaction = {
297
+ value: transactionRequest.value,
298
+ to: transactionRequest.to,
299
+ data: transactionRequest.data,
355
300
  }
301
+ multisigBatchTransactions.push(populatedTransaction)
356
302
 
357
- process = this.statusManager.updateProcess(
358
- step,
359
- process.type,
360
- 'ACTION_REQUIRED'
303
+ txHash = await this.multisig?.sendBatchTransaction(
304
+ multisigBatchTransactions
305
+ )
306
+ } else {
307
+ throw new TransactionError(
308
+ LiFiErrorCode.TransactionUnprepared,
309
+ 'Unable to prepare transaction.'
361
310
  )
362
311
  }
363
-
364
- txHash = await sendTransaction(this.client, {
312
+ } else {
313
+ txHash = await getAction(
314
+ this.client,
315
+ sendTransaction,
316
+ 'sendTransaction'
317
+ )({
365
318
  to: transactionRequest.to,
366
319
  account: this.client.account!,
367
320
  data: transactionRequest.data,
@@ -370,53 +323,61 @@ export class EVMStepExecutor extends BaseStepExecutor {
370
323
  gasPrice: transactionRequest.gasPrice,
371
324
  maxFeePerGas: transactionRequest.maxFeePerGas,
372
325
  maxPriorityFeePerGas: transactionRequest.maxPriorityFeePerGas,
326
+ chain: null,
373
327
  } as SendTransactionParameters)
374
328
  }
375
329
 
376
- // STEP 4: Wait for the transaction
377
- process = this.statusManager.updateProcess(
378
- step,
379
- process.type,
380
- 'PENDING',
381
- // When atomic batch is supported, txHash represents the batch hash rather than an individual transaction hash at this point
382
- atomicBatchSupported
383
- ? {
384
- atomicBatchSupported,
385
- }
386
- : {
387
- txHash: txHash,
388
- txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${txHash}`,
389
- }
390
- )
330
+ if (isMultisigClient) {
331
+ process = this.statusManager.updateProcess(
332
+ step,
333
+ process.type,
334
+ 'ACTION_REQUIRED',
335
+ {
336
+ multisigTxHash: txHash,
337
+ }
338
+ )
339
+ } else {
340
+ process = this.statusManager.updateProcess(
341
+ step,
342
+ process.type,
343
+ 'PENDING',
344
+ {
345
+ txHash: txHash,
346
+ txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${txHash}`,
347
+ }
348
+ )
349
+ }
391
350
  }
392
351
 
393
- let transactionReceipt:
394
- | TransactionReceipt
395
- | WalletCallReceipt
396
- | undefined
352
+ const transactionReceipt = await waitForTransactionReceipt({
353
+ client: this.client,
354
+ chainId: fromChain.id,
355
+ txHash,
356
+ onReplaced: (response) => {
357
+ this.statusManager.updateProcess(step, process.type, 'PENDING', {
358
+ txHash: response.transaction.hash,
359
+ txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
360
+ })
361
+ },
362
+ })
397
363
 
398
- if (atomicBatchSupported) {
399
- transactionReceipt = await waitForBatchTransactionReceipt(
400
- this.client,
401
- txHash
364
+ // if it's multisig wallet client and the process is in ACTION_REQUIRED
365
+ // then signatures are still needed
366
+ if (isMultisigClient && process.status === 'ACTION_REQUIRED') {
367
+ await updateMultisigRouteProcess(
368
+ transactionReceipt?.transactionHash || txHash,
369
+ step,
370
+ process.type,
371
+ fromChain,
372
+ this.statusManager,
373
+ this.multisig
402
374
  )
403
- } else {
404
- transactionReceipt = await waitForTransactionReceipt({
405
- client: this.client,
406
- chainId: fromChain.id,
407
- txHash,
408
- onReplaced: (response) => {
409
- this.statusManager.updateProcess(step, process.type, 'PENDING', {
410
- txHash: response.transaction.hash,
411
- txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
412
- })
413
- },
414
- })
415
375
  }
416
376
 
417
377
  // Update pending process if the transaction hash from the receipt is different.
418
378
  // This might happen if the transaction was replaced.
419
379
  if (
380
+ !isMultisigClient &&
420
381
  transactionReceipt?.transactionHash &&
421
382
  transactionReceipt.transactionHash !== txHash
422
383
  ) {
@@ -453,8 +414,7 @@ export class EVMStepExecutor extends BaseStepExecutor {
453
414
  }
454
415
  }
455
416
 
456
- // STEP 5: Wait for the receiving chain
457
- const processTxHash = process.txHash
417
+ // Wait for the transaction status on the destination chain
458
418
  if (isBridgeExecution) {
459
419
  process = this.statusManager.findOrCreateProcess({
460
420
  step,
@@ -464,61 +424,12 @@ export class EVMStepExecutor extends BaseStepExecutor {
464
424
  })
465
425
  }
466
426
 
467
- try {
468
- if (!processTxHash) {
469
- throw new Error('Transaction hash is undefined.')
470
- }
471
- const statusResponse = (await waitForReceivingTransaction(
472
- processTxHash,
473
- this.statusManager,
474
- process.type,
475
- step
476
- )) as FullStatusData
477
-
478
- const statusReceiving =
479
- statusResponse.receiving as ExtendedTransactionInfo
480
-
481
- process = this.statusManager.updateProcess(step, process.type, 'DONE', {
482
- substatus: statusResponse.substatus,
483
- substatusMessage:
484
- statusResponse.substatusMessage ||
485
- getSubstatusMessage(statusResponse.status, statusResponse.substatus),
486
- txHash: statusReceiving?.txHash,
487
- txLink: `${toChain.metamask.blockExplorerUrls[0]}tx/${statusReceiving?.txHash}`,
488
- })
489
-
490
- this.statusManager.updateExecution(step, 'DONE', {
491
- fromAmount: statusResponse.sending.amount,
492
- toAmount: statusReceiving?.amount,
493
- toToken: statusReceiving?.token,
494
- gasCosts: [
495
- {
496
- amount: statusResponse.sending.gasAmount,
497
- amountUSD: statusResponse.sending.gasAmountUSD,
498
- token: statusResponse.sending.gasToken,
499
- estimate: statusResponse.sending.gasUsed,
500
- limit: statusResponse.sending.gasUsed,
501
- price: statusResponse.sending.gasPrice,
502
- type: 'SEND',
503
- },
504
- ],
505
- })
506
- } catch (e: unknown) {
507
- const htmlMessage = await getTransactionFailedMessage(
508
- step,
509
- process.txLink
510
- )
511
-
512
- process = this.statusManager.updateProcess(step, process.type, 'FAILED', {
513
- error: {
514
- code: LiFiErrorCode.TransactionFailed,
515
- message: 'Failed while waiting for receiving chain.',
516
- htmlMessage,
517
- },
518
- })
519
- this.statusManager.updateExecution(step, 'FAILED')
520
- throw await parseEVMErrors(e as Error, step, process)
521
- }
427
+ await waitForDestinationChainTransaction(
428
+ step,
429
+ process,
430
+ this.statusManager,
431
+ toChain
432
+ )
522
433
 
523
434
  // DONE
524
435
  return step
@@ -1,44 +1,47 @@
1
- import { parseAbi } from 'viem'
1
+ import type { Abi } from 'viem'
2
2
 
3
- export const permit2ProxyAbi = parseAbi([
4
- 'function callDiamondWithPermit2(bytes, ((address, uint256), uint256, uint256), bytes) external',
5
- 'function callDiamondWithEIP2612Signature(address, uint256, uint256, uint8, bytes32, bytes32, bytes) external payable',
6
- 'function nextNonce(address) external view returns (uint256)',
7
- 'function callDiamondWithPermit2Witness(bytes, address, ((address, uint256), uint256, uint256), bytes) external payable',
8
- ])
3
+ export const approveAbi: Abi = [
4
+ {
5
+ name: 'approve',
6
+ inputs: [
7
+ { internalType: 'address', name: 'spender', type: 'address' },
8
+ { internalType: 'uint256', name: 'amount', type: 'uint256' },
9
+ ],
10
+ outputs: [{ internalType: 'bool', name: 'approved', type: 'bool' }],
11
+ stateMutability: 'nonpayable',
12
+ type: 'function',
13
+ },
14
+ ]
9
15
 
10
- export const eip2612Abi = parseAbi([
11
- 'function permit(address, address, uint256, uint256, uint8, bytes32, bytes32) external',
12
- 'function DOMAIN_SEPARATOR() external view returns (bytes32)',
13
- 'function nonces(address) external view returns (uint256)',
14
- 'function name() external view returns (string)',
15
- 'function version() external view returns (string)',
16
- ])
16
+ export const allowanceAbi: Abi = [
17
+ {
18
+ name: 'allowance',
19
+ inputs: [
20
+ { internalType: 'address', name: 'owner', type: 'address' },
21
+ { internalType: 'address', name: 'spender', type: 'address' },
22
+ ],
23
+ outputs: [{ internalType: 'uint256', name: 'allowance', type: 'uint256' }],
24
+ stateMutability: 'view',
25
+ type: 'function',
26
+ },
27
+ ]
17
28
 
18
- export const approveAbi = parseAbi([
19
- 'function approve(address, uint256) external returns (bool)',
20
- ])
29
+ export const getEthBalanceAbi: Abi = [
30
+ {
31
+ inputs: [{ name: '_owner', type: 'address' }],
32
+ name: 'getEthBalance',
33
+ outputs: [{ name: 'balance', type: 'uint256' }],
34
+ type: 'function',
35
+ stateMutability: 'view',
36
+ },
37
+ ]
21
38
 
22
- export const allowanceAbi = parseAbi([
23
- 'function allowance(address, address) external view returns (uint256)',
24
- ])
25
-
26
- export const getEthBalanceAbi = parseAbi([
27
- 'function getEthBalance(address) external view returns (uint256)',
28
- ])
29
-
30
- export const balanceOfAbi = parseAbi([
31
- 'function balanceOf(address) external view returns (uint256)',
32
- ])
33
-
34
- // EIP-2612 types
35
- // https://eips.ethereum.org/EIPS/eip-2612
36
- export const eip2612Types = {
37
- Permit: [
38
- { name: 'owner', type: 'address' },
39
- { name: 'spender', type: 'address' },
40
- { name: 'value', type: 'uint256' },
41
- { name: 'nonce', type: 'uint256' },
42
- { name: 'deadline', type: 'uint256' },
43
- ],
44
- } as const
39
+ export const balanceOfAbi: Abi = [
40
+ {
41
+ inputs: [{ name: '_owner', type: 'address' }],
42
+ name: 'balanceOf',
43
+ outputs: [{ name: 'balance', type: 'uint256' }],
44
+ type: 'function',
45
+ stateMutability: 'view',
46
+ },
47
+ ]