@lifi/sdk 3.5.1-beta.0 → 3.6.0-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 (224) hide show
  1. package/package.json +6 -3
  2. package/src/_cjs/constants.js +4 -2
  3. package/src/_cjs/constants.js.map +1 -1
  4. package/src/_cjs/core/EVM/EVM.js +0 -4
  5. package/src/_cjs/core/EVM/EVM.js.map +1 -1
  6. package/src/_cjs/core/EVM/EVMStepExecutor.js +156 -81
  7. package/src/_cjs/core/EVM/EVMStepExecutor.js.map +1 -1
  8. package/src/_cjs/core/EVM/abi.js +36 -43
  9. package/src/_cjs/core/EVM/abi.js.map +1 -1
  10. package/src/_cjs/core/EVM/checkAllowance.js +36 -30
  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/getNativePermit.js +90 -0
  15. package/src/_cjs/core/EVM/getNativePermit.js.map +1 -0
  16. package/src/_cjs/core/EVM/parseEVMErrors.js +5 -2
  17. package/src/_cjs/core/EVM/parseEVMErrors.js.map +1 -1
  18. package/src/_cjs/core/EVM/permit2/allowanceTransfer.js +100 -0
  19. package/src/_cjs/core/EVM/permit2/allowanceTransfer.js.map +1 -0
  20. package/src/_cjs/core/EVM/permit2/constants.js +12 -0
  21. package/src/_cjs/core/EVM/permit2/constants.js.map +1 -0
  22. package/src/_cjs/core/EVM/permit2/domain.js +12 -0
  23. package/src/_cjs/core/EVM/permit2/domain.js.map +1 -0
  24. package/src/_cjs/core/EVM/permit2/signatureTransfer.js +121 -0
  25. package/src/_cjs/core/EVM/permit2/signatureTransfer.js.map +1 -0
  26. package/src/_cjs/core/EVM/setAllowance.js +3 -4
  27. package/src/_cjs/core/EVM/setAllowance.js.map +1 -1
  28. package/src/_cjs/core/EVM/signPermitMessage.js +169 -0
  29. package/src/_cjs/core/EVM/signPermitMessage.js.map +1 -0
  30. package/src/_cjs/core/EVM/typeguards.js +8 -0
  31. package/src/_cjs/core/EVM/typeguards.js.map +1 -0
  32. package/src/_cjs/core/EVM/types.js.map +1 -1
  33. package/src/_cjs/core/EVM/utils.js +2 -1
  34. package/src/_cjs/core/EVM/utils.js.map +1 -1
  35. package/src/_cjs/core/EVM/waitForBatchTransactionReceipt.js +32 -0
  36. package/src/_cjs/core/EVM/waitForBatchTransactionReceipt.js.map +1 -0
  37. package/src/_cjs/core/EVM/waitForRelayedTransactionReceipt.js +38 -0
  38. package/src/_cjs/core/EVM/waitForRelayedTransactionReceipt.js.map +1 -0
  39. package/src/_cjs/core/checkBalance.js +3 -3
  40. package/src/_cjs/core/checkBalance.js.map +1 -1
  41. package/src/_cjs/core/waitForTransactionStatus.js +4 -2
  42. package/src/_cjs/core/waitForTransactionStatus.js.map +1 -1
  43. package/src/_cjs/createConfig.js +2 -2
  44. package/src/_cjs/createConfig.js.map +1 -1
  45. package/src/_cjs/errors/constants.js +1 -0
  46. package/src/_cjs/errors/constants.js.map +1 -1
  47. package/src/_cjs/index.js +9 -6
  48. package/src/_cjs/index.js.map +1 -1
  49. package/src/_cjs/services/api.js +127 -53
  50. package/src/_cjs/services/api.js.map +1 -1
  51. package/src/_cjs/utils/checkPackageUpdates.js +20 -0
  52. package/src/_cjs/utils/checkPackageUpdates.js.map +1 -0
  53. package/src/_cjs/utils/convertQuoteToRoute.js +33 -0
  54. package/src/_cjs/utils/convertQuoteToRoute.js.map +1 -0
  55. package/src/_cjs/utils/fetchTxErrorDetails.js +13 -0
  56. package/src/_cjs/utils/fetchTxErrorDetails.js.map +1 -0
  57. package/src/_cjs/utils/invariant.js +17 -0
  58. package/src/_cjs/utils/invariant.js.map +1 -0
  59. package/src/_cjs/utils/waitForResult.js +16 -3
  60. package/src/_cjs/utils/waitForResult.js.map +1 -1
  61. package/src/_cjs/version.js +1 -1
  62. package/src/_esm/constants.js +3 -1
  63. package/src/_esm/constants.js.map +1 -1
  64. package/src/_esm/core/EVM/EVM.js +0 -4
  65. package/src/_esm/core/EVM/EVM.js.map +1 -1
  66. package/src/_esm/core/EVM/EVMStepExecutor.js +186 -92
  67. package/src/_esm/core/EVM/EVMStepExecutor.js.map +1 -1
  68. package/src/_esm/core/EVM/abi.js +37 -42
  69. package/src/_esm/core/EVM/abi.js.map +1 -1
  70. package/src/_esm/core/EVM/checkAllowance.js +41 -32
  71. package/src/_esm/core/EVM/checkAllowance.js.map +1 -1
  72. package/src/_esm/core/EVM/getAllowance.js.map +1 -1
  73. package/src/_esm/core/EVM/getEVMBalance.js.map +1 -1
  74. package/src/_esm/core/EVM/getNativePermit.js +95 -0
  75. package/src/_esm/core/EVM/getNativePermit.js.map +1 -0
  76. package/src/_esm/core/EVM/parseEVMErrors.js +9 -1
  77. package/src/_esm/core/EVM/parseEVMErrors.js.map +1 -1
  78. package/src/_esm/core/EVM/permit2/allowanceTransfer.js +93 -0
  79. package/src/_esm/core/EVM/permit2/allowanceTransfer.js.map +1 -0
  80. package/src/_esm/core/EVM/permit2/constants.js +9 -0
  81. package/src/_esm/core/EVM/permit2/constants.js.map +1 -0
  82. package/src/_esm/core/EVM/permit2/domain.js +9 -0
  83. package/src/_esm/core/EVM/permit2/domain.js.map +1 -0
  84. package/src/_esm/core/EVM/permit2/signatureTransfer.js +117 -0
  85. package/src/_esm/core/EVM/permit2/signatureTransfer.js.map +1 -0
  86. package/src/_esm/core/EVM/setAllowance.js +3 -4
  87. package/src/_esm/core/EVM/setAllowance.js.map +1 -1
  88. package/src/_esm/core/EVM/signPermitMessage.js +163 -0
  89. package/src/_esm/core/EVM/signPermitMessage.js.map +1 -0
  90. package/src/_esm/core/EVM/typeguards.js +5 -0
  91. package/src/_esm/core/EVM/typeguards.js.map +1 -0
  92. package/src/_esm/core/EVM/types.js.map +1 -1
  93. package/src/_esm/core/EVM/utils.js +2 -1
  94. package/src/_esm/core/EVM/utils.js.map +1 -1
  95. package/src/_esm/core/EVM/waitForBatchTransactionReceipt.js +28 -0
  96. package/src/_esm/core/EVM/waitForBatchTransactionReceipt.js.map +1 -0
  97. package/src/_esm/core/EVM/waitForRelayedTransactionReceipt.js +34 -0
  98. package/src/_esm/core/EVM/waitForRelayedTransactionReceipt.js.map +1 -0
  99. package/src/_esm/core/checkBalance.js +3 -3
  100. package/src/_esm/core/checkBalance.js.map +1 -1
  101. package/src/_esm/core/waitForTransactionStatus.js +4 -2
  102. package/src/_esm/core/waitForTransactionStatus.js.map +1 -1
  103. package/src/_esm/createConfig.js +1 -1
  104. package/src/_esm/createConfig.js.map +1 -1
  105. package/src/_esm/errors/constants.js +1 -0
  106. package/src/_esm/errors/constants.js.map +1 -1
  107. package/src/_esm/index.js +4 -2
  108. package/src/_esm/index.js.map +1 -1
  109. package/src/_esm/services/api.js +165 -72
  110. package/src/_esm/services/api.js.map +1 -1
  111. package/src/_esm/utils/checkPackageUpdates.js +17 -0
  112. package/src/_esm/utils/checkPackageUpdates.js.map +1 -0
  113. package/src/_esm/utils/convertQuoteToRoute.js +37 -0
  114. package/src/_esm/utils/convertQuoteToRoute.js.map +1 -0
  115. package/src/_esm/utils/fetchTxErrorDetails.js +9 -0
  116. package/src/_esm/utils/fetchTxErrorDetails.js.map +1 -0
  117. package/src/_esm/utils/invariant.js +43 -0
  118. package/src/_esm/utils/invariant.js.map +1 -0
  119. package/src/_esm/utils/waitForResult.js +19 -3
  120. package/src/_esm/utils/waitForResult.js.map +1 -1
  121. package/src/_esm/version.js +1 -1
  122. package/src/_types/constants.d.ts +3 -1
  123. package/src/_types/constants.d.ts.map +1 -1
  124. package/src/_types/core/EVM/EVM.d.ts.map +1 -1
  125. package/src/_types/core/EVM/EVMStepExecutor.d.ts +7 -4
  126. package/src/_types/core/EVM/EVMStepExecutor.d.ts.map +1 -1
  127. package/src/_types/core/EVM/abi.d.ts +202 -5
  128. package/src/_types/core/EVM/abi.d.ts.map +1 -1
  129. package/src/_types/core/EVM/checkAllowance.d.ts +12 -2
  130. package/src/_types/core/EVM/checkAllowance.d.ts.map +1 -1
  131. package/src/_types/core/EVM/getAllowance.d.ts +5 -4
  132. package/src/_types/core/EVM/getAllowance.d.ts.map +1 -1
  133. package/src/_types/core/EVM/getEVMBalance.d.ts +2 -1
  134. package/src/_types/core/EVM/getEVMBalance.d.ts.map +1 -1
  135. package/src/_types/core/EVM/getNativePermit.d.ts +18 -0
  136. package/src/_types/core/EVM/getNativePermit.d.ts.map +1 -0
  137. package/src/_types/core/EVM/permit2/allowanceTransfer.d.ts +41 -0
  138. package/src/_types/core/EVM/permit2/allowanceTransfer.d.ts.map +1 -0
  139. package/src/_types/core/EVM/permit2/constants.d.ts +8 -0
  140. package/src/_types/core/EVM/permit2/constants.d.ts.map +1 -0
  141. package/src/_types/core/EVM/permit2/domain.d.ts +8 -0
  142. package/src/_types/core/EVM/permit2/domain.d.ts.map +1 -0
  143. package/src/_types/core/EVM/permit2/signatureTransfer.d.ts +42 -0
  144. package/src/_types/core/EVM/permit2/signatureTransfer.d.ts.map +1 -0
  145. package/src/_types/core/EVM/setAllowance.d.ts +2 -2
  146. package/src/_types/core/EVM/setAllowance.d.ts.map +1 -1
  147. package/src/_types/core/EVM/signPermitMessage.d.ts +25 -0
  148. package/src/_types/core/EVM/signPermitMessage.d.ts.map +1 -0
  149. package/src/_types/core/EVM/typeguards.d.ts +4 -0
  150. package/src/_types/core/EVM/typeguards.d.ts.map +1 -0
  151. package/src/_types/core/EVM/types.d.ts +8 -18
  152. package/src/_types/core/EVM/types.d.ts.map +1 -1
  153. package/src/_types/core/EVM/utils.d.ts +2 -2
  154. package/src/_types/core/EVM/utils.d.ts.map +1 -1
  155. package/src/_types/core/EVM/waitForBatchTransactionReceipt.d.ts +4 -0
  156. package/src/_types/core/EVM/waitForBatchTransactionReceipt.d.ts.map +1 -0
  157. package/src/_types/core/EVM/waitForRelayedTransactionReceipt.d.ts +4 -0
  158. package/src/_types/core/EVM/waitForRelayedTransactionReceipt.d.ts.map +1 -0
  159. package/src/_types/core/checkBalance.d.ts.map +1 -1
  160. package/src/_types/core/waitForTransactionStatus.d.ts.map +1 -1
  161. package/src/_types/createConfig.d.ts.map +1 -1
  162. package/src/_types/errors/constants.d.ts +2 -1
  163. package/src/_types/errors/constants.d.ts.map +1 -1
  164. package/src/_types/index.d.ts +5 -3
  165. package/src/_types/index.d.ts.map +1 -1
  166. package/src/_types/services/api.d.ts +93 -26
  167. package/src/_types/services/api.d.ts.map +1 -1
  168. package/src/_types/utils/checkPackageUpdates.d.ts +2 -0
  169. package/src/_types/utils/checkPackageUpdates.d.ts.map +1 -0
  170. package/src/_types/utils/convertQuoteToRoute.d.ts +11 -0
  171. package/src/_types/utils/convertQuoteToRoute.d.ts.map +1 -0
  172. package/src/_types/utils/fetchTxErrorDetails.d.ts +2 -0
  173. package/src/_types/utils/fetchTxErrorDetails.d.ts.map +1 -0
  174. package/src/_types/utils/invariant.d.ts +22 -0
  175. package/src/_types/utils/invariant.d.ts.map +1 -0
  176. package/src/_types/utils/waitForResult.d.ts +4 -1
  177. package/src/_types/utils/waitForResult.d.ts.map +1 -1
  178. package/src/_types/version.d.ts +1 -1
  179. package/src/constants.ts +6 -1
  180. package/src/core/EVM/EVM.ts +0 -4
  181. package/src/core/EVM/EVMStepExecutor.ts +242 -146
  182. package/src/core/EVM/abi.ts +40 -43
  183. package/src/core/EVM/checkAllowance.ts +96 -92
  184. package/src/core/EVM/getAllowance.ts +8 -8
  185. package/src/core/EVM/getEVMBalance.ts +2 -2
  186. package/src/core/EVM/getNativePermit.ts +114 -0
  187. package/src/core/EVM/parseEVMErrors.ts +9 -1
  188. package/src/core/EVM/permit2/allowanceTransfer.ts +168 -0
  189. package/src/core/EVM/permit2/constants.ts +11 -0
  190. package/src/core/EVM/permit2/domain.ts +20 -0
  191. package/src/core/EVM/permit2/signatureTransfer.ts +214 -0
  192. package/src/core/EVM/setAllowance.ts +14 -15
  193. package/src/core/EVM/signPermitMessage.ts +280 -0
  194. package/src/core/EVM/typeguards.ts +7 -0
  195. package/src/core/EVM/types.ts +11 -26
  196. package/src/core/EVM/utils.ts +4 -3
  197. package/src/core/EVM/waitForBatchTransactionReceipt.ts +61 -0
  198. package/src/core/EVM/waitForRelayedTransactionReceipt.ts +50 -0
  199. package/src/core/checkBalance.ts +6 -3
  200. package/src/core/waitForTransactionStatus.ts +6 -2
  201. package/src/createConfig.ts +1 -1
  202. package/src/errors/constants.ts +1 -0
  203. package/src/index.ts +4 -8
  204. package/src/services/api.ts +279 -105
  205. package/src/utils/checkPackageUpdates.ts +22 -0
  206. package/src/utils/convertQuoteToRoute.ts +45 -0
  207. package/src/utils/fetchTxErrorDetails.ts +10 -0
  208. package/src/utils/invariant.ts +51 -0
  209. package/src/utils/waitForResult.ts +22 -3
  210. package/src/version.ts +1 -1
  211. package/src/_cjs/core/EVM/multisig.js +0 -29
  212. package/src/_cjs/core/EVM/multisig.js.map +0 -1
  213. package/src/_cjs/helpers.js +0 -55
  214. package/src/_cjs/helpers.js.map +0 -1
  215. package/src/_esm/core/EVM/multisig.js +0 -25
  216. package/src/_esm/core/EVM/multisig.js.map +0 -1
  217. package/src/_esm/helpers.js +0 -58
  218. package/src/_esm/helpers.js.map +0 -1
  219. package/src/_types/core/EVM/multisig.d.ts +0 -6
  220. package/src/_types/core/EVM/multisig.d.ts.map +0 -1
  221. package/src/_types/helpers.d.ts +0 -13
  222. package/src/_types/helpers.d.ts.map +0 -1
  223. package/src/core/EVM/multisig.ts +0 -54
  224. package/src/helpers.ts +0 -75
@@ -1,16 +1,25 @@
1
- import type { Process } from '@lifi/types'
1
+ import type { LiFiStep, Process } from '@lifi/types'
2
2
  import type {
3
+ Address,
3
4
  Client,
4
5
  GetAddressesReturnType,
5
6
  Hash,
7
+ Hex,
6
8
  SendTransactionParameters,
9
+ TransactionReceipt,
7
10
  } from 'viem'
8
- import { getAddresses, sendTransaction } from 'viem/actions'
11
+ import { estimateGas, getAddresses, sendTransaction } from 'viem/actions'
12
+ import type { GetCapabilitiesReturnType } from 'viem/experimental'
13
+ import { getCapabilities, sendCalls } from 'viem/experimental'
9
14
  import { getAction } from 'viem/utils'
10
15
  import { config } from '../../config.js'
11
16
  import { LiFiErrorCode } from '../../errors/constants.js'
12
- import { TransactionError, ValidationError } from '../../errors/errors.js'
13
- import { getStepTransaction } from '../../services/api.js'
17
+ import { TransactionError } from '../../errors/errors.js'
18
+ import {
19
+ getRelayerQuote,
20
+ getStepTransaction,
21
+ relayTransaction,
22
+ } from '../../services/api.js'
14
23
  import { isZeroAddress } from '../../utils/isZeroAddress.js'
15
24
  import { BaseStepExecutor } from '../BaseStepExecutor.js'
16
25
  import { checkBalance } from '../checkBalance.js'
@@ -22,33 +31,40 @@ import type {
22
31
  } from '../types.js'
23
32
  import { waitForDestinationChainTransaction } from '../waitForDestinationChainTransaction.js'
24
33
  import { checkAllowance } from './checkAllowance.js'
25
- import { updateMultisigRouteProcess } from './multisig.js'
34
+ import { getNativePermit } from './getNativePermit.js'
26
35
  import { parseEVMErrors } from './parseEVMErrors.js'
36
+ import { type PermitSignature, signPermitMessage } from './signPermitMessage.js'
27
37
  import { switchChain } from './switchChain.js'
28
- import type { MultisigConfig, MultisigTransaction } from './types.js'
38
+ import { isEVMPermitStep } from './typeguards.js'
29
39
  import { getMaxPriorityFeePerGas } from './utils.js'
40
+ import {
41
+ type WalletCallReceipt,
42
+ waitForBatchTransactionReceipt,
43
+ } from './waitForBatchTransactionReceipt.js'
44
+ import { waitForRelayedTransactionReceipt } from './waitForRelayedTransactionReceipt.js'
30
45
  import { waitForTransactionReceipt } from './waitForTransactionReceipt.js'
31
46
 
47
+ export type Call = {
48
+ data?: Hex
49
+ to?: Address
50
+ value?: bigint
51
+ chainId?: number
52
+ }
53
+
32
54
  export interface EVMStepExecutorOptions extends StepExecutorOptions {
33
55
  client: Client
34
- multisig?: MultisigConfig
35
56
  }
36
57
 
37
58
  export class EVMStepExecutor extends BaseStepExecutor {
38
59
  private client: Client
39
- private multisig?: MultisigConfig
40
60
 
41
61
  constructor(options: EVMStepExecutorOptions) {
42
62
  super(options)
43
63
  this.client = options.client
44
- this.multisig = options.multisig
45
64
  }
46
65
 
47
66
  // Ensure that we are using the right chain and wallet when executing transactions.
48
- checkClient = async (
49
- step: LiFiStepExtended,
50
- process?: Process
51
- ): Promise<Client | undefined> => {
67
+ checkClient = async (step: LiFiStepExtended, process?: Process) => {
52
68
  const updatedClient = await switchChain(
53
69
  this.client,
54
70
  this.statusManager,
@@ -119,49 +135,88 @@ export class EVMStepExecutor extends BaseStepExecutor {
119
135
  }
120
136
  }
121
137
 
122
- const isMultisigClient = !!this.multisig?.isMultisigWalletClient
123
- const multisigBatchTransactions: MultisigTransaction[] = []
124
-
125
- const shouldBatchTransactions =
126
- this.multisig?.shouldBatchTransactions &&
127
- !!this.multisig.sendBatchTransaction
128
-
129
138
  const fromChain = await config.getChainById(step.action.fromChainId)
130
139
  const toChain = await config.getChainById(step.action.toChainId)
131
140
 
141
+ let atomicBatchSupported = false
142
+ try {
143
+ const capabilities = (await getAction(
144
+ this.client,
145
+ getCapabilities,
146
+ 'getCapabilities'
147
+ )(undefined)) as GetCapabilitiesReturnType
148
+ atomicBatchSupported = capabilities[fromChain.id]?.atomicBatch?.supported
149
+ } catch {
150
+ // If the wallet does not support getCapabilities, we assume that atomic batch is not supported
151
+ }
152
+
153
+ const calls: Call[] = []
154
+
132
155
  const isBridgeExecution = fromChain.id !== toChain.id
133
156
  const currentProcessType = isBridgeExecution ? 'CROSS_CHAIN' : 'SWAP'
134
157
 
135
- // Check allowance
158
+ // Find existing swap/bridge process
136
159
  const existingProcess = step.execution.process.find(
137
160
  (p) => p.type === currentProcessType
138
161
  )
139
162
 
140
- // Check token approval only if fromToken is not the native token => no approval needed in that case
163
+ // Check if step requires permit signature and will be used with relayer service
164
+ const isPermitStep = isEVMPermitStep(step)
165
+
166
+ // Check if token requires approval
167
+ // Native tokens (like ETH) don't need approval since they're not ERC20 tokens
168
+ // We should support different permit types:
169
+ // 1. Native permits (EIP-2612)
170
+ // 2. Permit2 - Universal permit implementation by Uniswap (limited to certain chains)
171
+ // 3. Standard ERC20 approval
172
+ const nativePermit = await getNativePermit(
173
+ this.client,
174
+ fromChain,
175
+ step.action.fromToken.address as Address
176
+ )
177
+ // Check if proxy contract is available and token supports native permits, not available for atomic batch
178
+ const nativePermitSupported =
179
+ !!fromChain.permit2Proxy &&
180
+ nativePermit.supported &&
181
+ !atomicBatchSupported &&
182
+ !isPermitStep
183
+ // Check if chain has Permit2 contract deployed. Permit2 should not be available for atomic batch.
184
+ const permit2Supported =
185
+ !!fromChain.permit2 && !!fromChain.permit2Proxy && !atomicBatchSupported
186
+ // Token supports either native permits or Permit2
187
+ const permitSupported = permit2Supported || nativePermitSupported
188
+
141
189
  const checkForAllowance =
190
+ // No existing swap/bridgetransaction is pending
142
191
  !existingProcess?.txHash &&
192
+ // Token is not native (address is not zero)
143
193
  !isZeroAddress(step.action.fromToken.address) &&
144
- (shouldBatchTransactions || !isMultisigClient)
194
+ // Token doesn't support native permits
195
+ !nativePermitSupported
145
196
 
146
197
  if (checkForAllowance) {
147
- const data = await checkAllowance(
148
- this.client,
149
- fromChain,
198
+ // Check if token needs approval and get approval transaction or message data when available
199
+ const data = await checkAllowance({
200
+ client: this.client,
201
+ chain: fromChain,
150
202
  step,
151
- this.statusManager,
152
- this.executionOptions,
153
- this.allowUserInteraction,
154
- shouldBatchTransactions
155
- )
203
+ statusManager: this.statusManager,
204
+ executionOptions: this.executionOptions,
205
+ allowUserInteraction: this.allowUserInteraction,
206
+ atomicBatchSupported,
207
+ permit2Supported,
208
+ })
156
209
 
157
210
  if (data) {
158
- // allowance doesn't need value
159
- const baseTransaction: MultisigTransaction = {
160
- to: step.action.fromToken.address,
161
- data,
211
+ // Create approval transaction call
212
+ // No value needed since we're only approving ERC20 tokens
213
+ if (atomicBatchSupported) {
214
+ calls.push({
215
+ chainId: step.action.fromToken.chainId,
216
+ to: step.action.fromToken.address as Address,
217
+ data,
218
+ })
162
219
  }
163
-
164
- multisigBatchTransactions.push(baseTransaction)
165
220
  }
166
221
  }
167
222
 
@@ -172,28 +227,7 @@ export class EVMStepExecutor extends BaseStepExecutor {
172
227
  })
173
228
 
174
229
  if (process.status !== 'DONE') {
175
- const multisigProcess = step.execution.process.find(
176
- (p) => !!p.multisigTxHash
177
- )
178
-
179
230
  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
-
197
231
  let txHash: Hash
198
232
  if (process.txHash) {
199
233
  // Make sure that the chain is still correct
@@ -214,10 +248,30 @@ export class EVMStepExecutor extends BaseStepExecutor {
214
248
  // Check balance
215
249
  await checkBalance(this.client.account!.address, step)
216
250
 
217
- // Create new transaction
251
+ // Create new transaction request
218
252
  if (!step.transactionRequest) {
219
253
  const { execution, ...stepBase } = step
220
- const updatedStep = await getStepTransaction(stepBase)
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
+ }
221
275
  const comparedStep = await stepComparison(
222
276
  this.statusManager,
223
277
  step,
@@ -238,22 +292,6 @@ export class EVMStepExecutor extends BaseStepExecutor {
238
292
  )
239
293
  }
240
294
 
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
-
257
295
  let transactionRequest: TransactionParameters = {
258
296
  to: step.transactionRequest.to,
259
297
  from: step.transactionRequest.from,
@@ -291,93 +329,151 @@ export class EVMStepExecutor extends BaseStepExecutor {
291
329
  }
292
330
  }
293
331
 
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,
300
- }
301
- multisigBatchTransactions.push(populatedTransaction)
332
+ // Make sure that the chain is still correct
333
+ const updatedClient = await this.checkClient(step, process)
334
+ if (!updatedClient) {
335
+ return step
336
+ }
302
337
 
303
- txHash = await this.multisig?.sendBatchTransaction(
304
- multisigBatchTransactions
305
- )
306
- } else {
307
- throw new TransactionError(
308
- LiFiErrorCode.TransactionUnprepared,
309
- 'Unable to prepare transaction.'
310
- )
338
+ process = this.statusManager.updateProcess(
339
+ step,
340
+ process.type,
341
+ permitSupported ? 'PERMIT_REQUIRED' : 'ACTION_REQUIRED'
342
+ )
343
+
344
+ if (!this.allowUserInteraction) {
345
+ return step
346
+ }
347
+
348
+ if (atomicBatchSupported) {
349
+ const transferCall: Call = {
350
+ chainId: fromChain.id,
351
+ data: transactionRequest.data as Hex,
352
+ to: transactionRequest.to as Address,
353
+ value: transactionRequest.value,
311
354
  }
312
- } else {
313
- txHash = await getAction(
355
+
356
+ calls.push(transferCall)
357
+
358
+ txHash = (await getAction(
314
359
  this.client,
315
- sendTransaction,
316
- 'sendTransaction'
360
+ sendCalls,
361
+ 'sendCalls'
317
362
  )({
318
- to: transactionRequest.to,
319
363
  account: this.client.account!,
320
- data: transactionRequest.data,
321
- value: transactionRequest.value,
322
- gas: transactionRequest.gas,
323
- gasPrice: transactionRequest.gasPrice,
324
- maxFeePerGas: transactionRequest.maxFeePerGas,
325
- maxPriorityFeePerGas: transactionRequest.maxPriorityFeePerGas,
326
- chain: null,
327
- } as SendTransactionParameters)
328
- }
329
-
330
- if (isMultisigClient) {
331
- process = this.statusManager.updateProcess(
332
- step,
333
- process.type,
334
- 'ACTION_REQUIRED',
335
- {
336
- multisigTxHash: txHash,
337
- }
338
- )
364
+ calls,
365
+ })) as Address
339
366
  } 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}`,
367
+ let permitSignature: PermitSignature | undefined
368
+ if (permitSupported) {
369
+ permitSignature = await signPermitMessage(this.client, {
370
+ transactionRequest,
371
+ chain: fromChain,
372
+ tokenAddress: step.action.fromToken.address as Address,
373
+ amount: BigInt(step.action.fromAmount),
374
+ nativePermit,
375
+ permitData: isPermitStep ? step.permitData : undefined,
376
+ useWitness: isPermitStep,
377
+ })
378
+
379
+ transactionRequest.to = fromChain.permit2Proxy
380
+ // If it's a permit step, we already have everything encoded in the data field
381
+ transactionRequest.data = isPermitStep
382
+ ? transactionRequest.data
383
+ : permitSignature.data
384
+
385
+ try {
386
+ // Try to re-estimate the gas due to additional Permit data
387
+ transactionRequest.gas = await estimateGas(this.client, {
388
+ account: this.client.account!,
389
+ to: transactionRequest.to as Address,
390
+ data: transactionRequest.data as Hex,
391
+ value: transactionRequest.value,
392
+ })
393
+ } catch {
394
+ // Let the wallet estimate the gas in case of failure
395
+ transactionRequest.gas = undefined
347
396
  }
348
- )
349
- }
350
- }
351
397
 
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
- })
398
+ process = this.statusManager.updateProcess(
399
+ step,
400
+ process.type,
401
+ 'ACTION_REQUIRED'
402
+ )
403
+ }
404
+ if (isPermitStep && permitSignature) {
405
+ const relayedTransaction = await relayTransaction({
406
+ tokenOwner: this.client.account!.address,
407
+ chainId: fromChain.id,
408
+ permit: step.permit,
409
+ witness: step.witness,
410
+ signedPermitData: permitSignature.signature,
411
+ callData: transactionRequest.data!,
412
+ })
413
+ txHash = relayedTransaction.data.taskId
414
+ } else {
415
+ txHash = await getAction(
416
+ this.client,
417
+ sendTransaction,
418
+ 'sendTransaction'
419
+ )({
420
+ to: transactionRequest.to,
421
+ account: this.client.account!,
422
+ data: transactionRequest.data,
423
+ value: transactionRequest.value,
424
+ gas: transactionRequest.gas,
425
+ gasPrice: transactionRequest.gasPrice,
426
+ maxFeePerGas: transactionRequest.maxFeePerGas,
427
+ maxPriorityFeePerGas: transactionRequest.maxPriorityFeePerGas,
428
+ } as SendTransactionParameters)
429
+ }
430
+ }
363
431
 
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,
432
+ process = this.statusManager.updateProcess(
369
433
  step,
370
434
  process.type,
371
- fromChain,
372
- this.statusManager,
373
- this.multisig
435
+ 'PENDING',
436
+ // When atomic batch is supported, txHash represents the batch hash rather than an individual transaction hash at this point
437
+ atomicBatchSupported
438
+ ? {
439
+ atomicBatchSupported,
440
+ }
441
+ : {
442
+ txHash: txHash,
443
+ txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${txHash}`,
444
+ }
445
+ )
446
+ }
447
+
448
+ let transactionReceipt:
449
+ | TransactionReceipt
450
+ | WalletCallReceipt
451
+ | undefined
452
+
453
+ if (atomicBatchSupported) {
454
+ transactionReceipt = await waitForBatchTransactionReceipt(
455
+ this.client,
456
+ txHash
374
457
  )
458
+ } else if (isPermitStep) {
459
+ transactionReceipt = await waitForRelayedTransactionReceipt(txHash)
460
+ } else {
461
+ transactionReceipt = await waitForTransactionReceipt({
462
+ client: this.client,
463
+ chainId: fromChain.id,
464
+ txHash,
465
+ onReplaced: (response) => {
466
+ this.statusManager.updateProcess(step, process.type, 'PENDING', {
467
+ txHash: response.transaction.hash,
468
+ txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
469
+ })
470
+ },
471
+ })
375
472
  }
376
473
 
377
474
  // Update pending process if the transaction hash from the receipt is different.
378
475
  // This might happen if the transaction was replaced.
379
476
  if (
380
- !isMultisigClient &&
381
477
  transactionReceipt?.transactionHash &&
382
478
  transactionReceipt.transactionHash !== txHash
383
479
  ) {
@@ -1,47 +1,44 @@
1
- import type { Abi } from 'viem'
1
+ import { parseAbi } from 'viem'
2
2
 
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
- ]
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
+ ])
15
9
 
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
- ]
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
+ ])
28
17
 
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
- ]
18
+ export const approveAbi = parseAbi([
19
+ 'function approve(address, uint256) external returns (bool)',
20
+ ])
38
21
 
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
- ]
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