@lifi/sdk 3.6.0-beta.5 → 3.6.0-beta.6

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 (233) hide show
  1. package/package.json +3 -3
  2. package/src/_cjs/config.js +3 -0
  3. package/src/_cjs/config.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 +136 -112
  7. package/src/_cjs/core/EVM/EVMStepExecutor.js.map +1 -1
  8. package/src/_cjs/core/EVM/checkAllowance.js +34 -5
  9. package/src/_cjs/core/EVM/checkAllowance.js.map +1 -1
  10. package/src/_cjs/core/EVM/checkPermitSupport.js +33 -0
  11. package/src/_cjs/core/EVM/checkPermitSupport.js.map +1 -0
  12. package/src/_cjs/core/EVM/parseEVMErrors.js +3 -0
  13. package/src/_cjs/core/EVM/parseEVMErrors.js.map +1 -1
  14. package/src/_cjs/core/EVM/{permit2 → permits}/allowanceTransfer.js.map +1 -1
  15. package/src/_cjs/core/EVM/{permit2 → permits}/constants.js.map +1 -1
  16. package/src/_cjs/core/EVM/{permit2 → permits}/domain.js.map +1 -1
  17. package/src/_cjs/core/EVM/permits/encodeNativePermitData.js +16 -0
  18. package/src/_cjs/core/EVM/permits/encodeNativePermitData.js.map +1 -0
  19. package/src/_cjs/core/EVM/permits/encodePermit2Data.js +32 -0
  20. package/src/_cjs/core/EVM/permits/encodePermit2Data.js.map +1 -0
  21. package/src/_cjs/core/EVM/{getNativePermit.js → permits/getNativePermit.js} +30 -21
  22. package/src/_cjs/core/EVM/permits/getNativePermit.js.map +1 -0
  23. package/src/_cjs/core/EVM/permits/getPermitTransferFromValues.js +24 -0
  24. package/src/_cjs/core/EVM/permits/getPermitTransferFromValues.js.map +1 -0
  25. package/src/_cjs/core/EVM/permits/signNativePermitMessage.js +20 -0
  26. package/src/_cjs/core/EVM/permits/signNativePermitMessage.js.map +1 -0
  27. package/src/_cjs/core/EVM/permits/signPermit2Message.js +43 -0
  28. package/src/_cjs/core/EVM/permits/signPermit2Message.js.map +1 -0
  29. package/src/_cjs/core/EVM/permits/signatureTransfer.js.map +1 -0
  30. package/src/_cjs/core/EVM/permits/types.js +3 -0
  31. package/src/_cjs/core/EVM/permits/types.js.map +1 -0
  32. package/src/_cjs/core/EVM/permits/utils.js +31 -0
  33. package/src/_cjs/core/EVM/permits/utils.js.map +1 -0
  34. package/src/_cjs/core/EVM/publicClient.js +32 -33
  35. package/src/_cjs/core/EVM/publicClient.js.map +1 -1
  36. package/src/_cjs/core/EVM/typeguards.js +1 -1
  37. package/src/_cjs/core/EVM/typeguards.js.map +1 -1
  38. package/src/_cjs/core/EVM/types.js.map +1 -1
  39. package/src/_cjs/core/EVM/waitForBatchTransactionReceipt.js +3 -2
  40. package/src/_cjs/core/EVM/waitForBatchTransactionReceipt.js.map +1 -1
  41. package/src/_cjs/core/EVM/waitForRelayedTransactionReceipt.js +4 -4
  42. package/src/_cjs/core/EVM/waitForRelayedTransactionReceipt.js.map +1 -1
  43. package/src/_cjs/core/checkBalance.js +2 -1
  44. package/src/_cjs/core/checkBalance.js.map +1 -1
  45. package/src/_cjs/core/utils.js +1 -1
  46. package/src/_cjs/core/utils.js.map +1 -1
  47. package/src/_cjs/errors/constants.js +1 -0
  48. package/src/_cjs/errors/constants.js.map +1 -1
  49. package/src/_cjs/services/api.js +18 -6
  50. package/src/_cjs/services/api.js.map +1 -1
  51. package/src/_cjs/version.js +1 -1
  52. package/src/_esm/config.js +3 -0
  53. package/src/_esm/config.js.map +1 -1
  54. package/src/_esm/core/EVM/EVM.js +4 -0
  55. package/src/_esm/core/EVM/EVM.js.map +1 -1
  56. package/src/_esm/core/EVM/EVMStepExecutor.js +140 -124
  57. package/src/_esm/core/EVM/EVMStepExecutor.js.map +1 -1
  58. package/src/_esm/core/EVM/checkAllowance.js +35 -5
  59. package/src/_esm/core/EVM/checkAllowance.js.map +1 -1
  60. package/src/_esm/core/EVM/checkPermitSupport.js +43 -0
  61. package/src/_esm/core/EVM/checkPermitSupport.js.map +1 -0
  62. package/src/_esm/core/EVM/parseEVMErrors.js +9 -0
  63. package/src/_esm/core/EVM/parseEVMErrors.js.map +1 -1
  64. package/src/_esm/core/EVM/{permit2 → permits}/allowanceTransfer.js.map +1 -1
  65. package/src/_esm/core/EVM/{permit2 → permits}/constants.js.map +1 -1
  66. package/src/_esm/core/EVM/{permit2 → permits}/domain.js.map +1 -1
  67. package/src/_esm/core/EVM/permits/encodeNativePermitData.js +12 -0
  68. package/src/_esm/core/EVM/permits/encodeNativePermitData.js.map +1 -0
  69. package/src/_esm/core/EVM/permits/encodePermit2Data.js +28 -0
  70. package/src/_esm/core/EVM/permits/encodePermit2Data.js.map +1 -0
  71. package/src/_esm/core/EVM/{getNativePermit.js → permits/getNativePermit.js} +30 -21
  72. package/src/_esm/core/EVM/permits/getNativePermit.js.map +1 -0
  73. package/src/_esm/core/EVM/permits/getPermitTransferFromValues.js +20 -0
  74. package/src/_esm/core/EVM/permits/getPermitTransferFromValues.js.map +1 -0
  75. package/src/_esm/core/EVM/permits/signNativePermitMessage.js +16 -0
  76. package/src/_esm/core/EVM/permits/signNativePermitMessage.js.map +1 -0
  77. package/src/_esm/core/EVM/permits/signPermit2Message.js +41 -0
  78. package/src/_esm/core/EVM/permits/signPermit2Message.js.map +1 -0
  79. package/src/_esm/core/EVM/{permit2 → permits}/signatureTransfer.js +0 -2
  80. package/src/_esm/core/EVM/{permit2 → permits}/signatureTransfer.js.map +1 -1
  81. package/src/_esm/core/EVM/permits/types.js +2 -0
  82. package/src/_esm/core/EVM/permits/types.js.map +1 -0
  83. package/src/_esm/core/EVM/permits/utils.js +26 -0
  84. package/src/_esm/core/EVM/permits/utils.js.map +1 -0
  85. package/src/_esm/core/EVM/publicClient.js +34 -35
  86. package/src/_esm/core/EVM/publicClient.js.map +1 -1
  87. package/src/_esm/core/EVM/typeguards.js +1 -1
  88. package/src/_esm/core/EVM/typeguards.js.map +1 -1
  89. package/src/_esm/core/EVM/types.js.map +1 -1
  90. package/src/_esm/core/EVM/waitForBatchTransactionReceipt.js +5 -2
  91. package/src/_esm/core/EVM/waitForBatchTransactionReceipt.js.map +1 -1
  92. package/src/_esm/core/EVM/waitForRelayedTransactionReceipt.js +4 -4
  93. package/src/_esm/core/EVM/waitForRelayedTransactionReceipt.js.map +1 -1
  94. package/src/_esm/core/checkBalance.js +2 -1
  95. package/src/_esm/core/checkBalance.js.map +1 -1
  96. package/src/_esm/core/utils.js +1 -1
  97. package/src/_esm/core/utils.js.map +1 -1
  98. package/src/_esm/errors/constants.js +1 -0
  99. package/src/_esm/errors/constants.js.map +1 -1
  100. package/src/_esm/services/api.js +18 -6
  101. package/src/_esm/services/api.js.map +1 -1
  102. package/src/_esm/version.js +1 -1
  103. package/src/_types/config.d.ts +2 -1
  104. package/src/_types/config.d.ts.map +1 -1
  105. package/src/_types/core/BaseStepExecutor.d.ts.map +1 -1
  106. package/src/_types/core/EVM/EVM.d.ts.map +1 -1
  107. package/src/_types/core/EVM/EVMStepExecutor.d.ts +4 -10
  108. package/src/_types/core/EVM/EVMStepExecutor.d.ts.map +1 -1
  109. package/src/_types/core/EVM/checkAllowance.d.ts +13 -2
  110. package/src/_types/core/EVM/checkAllowance.d.ts.map +1 -1
  111. package/src/_types/core/EVM/checkPermitSupport.d.ts +27 -0
  112. package/src/_types/core/EVM/checkPermitSupport.d.ts.map +1 -0
  113. package/src/_types/core/EVM/getAllowance.d.ts.map +1 -1
  114. package/src/_types/core/EVM/getENSAddress.d.ts.map +1 -1
  115. package/src/_types/core/EVM/getEVMBalance.d.ts.map +1 -1
  116. package/src/_types/core/EVM/parseEVMErrors.d.ts.map +1 -1
  117. package/src/_types/core/EVM/{permit2 → permits}/allowanceTransfer.d.ts.map +1 -1
  118. package/src/_types/core/EVM/{permit2 → permits}/constants.d.ts.map +1 -1
  119. package/src/_types/core/EVM/permits/domain.d.ts +3 -0
  120. package/src/_types/core/EVM/permits/domain.d.ts.map +1 -0
  121. package/src/_types/core/EVM/permits/encodeNativePermitData.d.ts +3 -0
  122. package/src/_types/core/EVM/permits/encodeNativePermitData.d.ts.map +1 -0
  123. package/src/_types/core/EVM/permits/encodePermit2Data.d.ts +4 -0
  124. package/src/_types/core/EVM/permits/encodePermit2Data.d.ts.map +1 -0
  125. package/src/_types/core/EVM/{getNativePermit.d.ts → permits/getNativePermit.d.ts} +2 -9
  126. package/src/_types/core/EVM/permits/getNativePermit.d.ts.map +1 -0
  127. package/src/_types/core/EVM/permits/getPermitTransferFromValues.d.ts +5 -0
  128. package/src/_types/core/EVM/permits/getPermitTransferFromValues.d.ts.map +1 -0
  129. package/src/_types/core/EVM/permits/signNativePermitMessage.d.ts +4 -0
  130. package/src/_types/core/EVM/permits/signNativePermitMessage.d.ts.map +1 -0
  131. package/src/_types/core/EVM/permits/signPermit2Message.d.ts +21 -0
  132. package/src/_types/core/EVM/permits/signPermit2Message.d.ts.map +1 -0
  133. package/src/_types/core/EVM/{permit2 → permits}/signatureTransfer.d.ts +15 -16
  134. package/src/_types/core/EVM/permits/signatureTransfer.d.ts.map +1 -0
  135. package/src/_types/core/EVM/permits/types.d.ts +24 -0
  136. package/src/_types/core/EVM/permits/types.d.ts.map +1 -0
  137. package/src/_types/core/EVM/permits/utils.d.ts +6 -0
  138. package/src/_types/core/EVM/permits/utils.d.ts.map +1 -0
  139. package/src/_types/core/EVM/publicClient.d.ts.map +1 -1
  140. package/src/_types/core/EVM/setAllowance.d.ts.map +1 -1
  141. package/src/_types/core/EVM/switchChain.d.ts.map +1 -1
  142. package/src/_types/core/EVM/typeguards.d.ts +2 -1
  143. package/src/_types/core/EVM/typeguards.d.ts.map +1 -1
  144. package/src/_types/core/EVM/types.d.ts +13 -7
  145. package/src/_types/core/EVM/types.d.ts.map +1 -1
  146. package/src/_types/core/EVM/utils.d.ts.map +1 -1
  147. package/src/_types/core/EVM/waitForBatchTransactionReceipt.d.ts.map +1 -1
  148. package/src/_types/core/EVM/waitForRelayedTransactionReceipt.d.ts.map +1 -1
  149. package/src/_types/core/Solana/SolanaStepExecutor.d.ts.map +1 -1
  150. package/src/_types/core/Solana/getSNSAddress.d.ts.map +1 -1
  151. package/src/_types/core/Solana/getSolanaBalance.d.ts.map +1 -1
  152. package/src/_types/core/Solana/parseSolanaErrors.d.ts.map +1 -1
  153. package/src/_types/core/StatusManager.d.ts.map +1 -1
  154. package/src/_types/core/UTXO/UTXOStepExecutor.d.ts.map +1 -1
  155. package/src/_types/core/UTXO/getUTXOAPIPublicClient.d.ts.map +1 -1
  156. package/src/_types/core/UTXO/getUTXOBalance.d.ts.map +1 -1
  157. package/src/_types/core/UTXO/getUTXOPublicClient.d.ts.map +1 -1
  158. package/src/_types/core/UTXO/parseUTXOErrors.d.ts.map +1 -1
  159. package/src/_types/core/checkBalance.d.ts.map +1 -1
  160. package/src/_types/core/execution.d.ts.map +1 -1
  161. package/src/_types/core/prepareRestart.d.ts.map +1 -1
  162. package/src/_types/core/provider.d.ts.map +1 -1
  163. package/src/_types/core/rpc.d.ts.map +1 -1
  164. package/src/_types/core/stepComparison.d.ts.map +1 -1
  165. package/src/_types/errors/constants.d.ts +2 -1
  166. package/src/_types/errors/constants.d.ts.map +1 -1
  167. package/src/_types/errors/utils/baseErrorRootCause.d.ts.map +1 -1
  168. package/src/_types/errors/utils/rootCause.d.ts.map +1 -1
  169. package/src/_types/request.d.ts.map +1 -1
  170. package/src/_types/services/api.d.ts +4 -47
  171. package/src/_types/services/api.d.ts.map +1 -1
  172. package/src/_types/services/balance.d.ts.map +1 -1
  173. package/src/_types/services/getNameServiceAddress.d.ts.map +1 -1
  174. package/src/_types/typeguards.d.ts.map +1 -1
  175. package/src/_types/utils/checkPackageUpdates.d.ts.map +1 -1
  176. package/src/_types/utils/convertQuoteToRoute.d.ts.map +1 -1
  177. package/src/_types/utils/fetchTxErrorDetails.d.ts.map +1 -1
  178. package/src/_types/utils/getTransactionMessage.d.ts.map +1 -1
  179. package/src/_types/utils/isZeroAddress.d.ts.map +1 -1
  180. package/src/_types/utils/median.d.ts.map +1 -1
  181. package/src/_types/utils/waitForResult.d.ts.map +1 -1
  182. package/src/_types/version.d.ts +1 -1
  183. package/src/config.ts +4 -1
  184. package/src/core/EVM/EVM.ts +4 -0
  185. package/src/core/EVM/EVMStepExecutor.ts +186 -149
  186. package/src/core/EVM/checkAllowance.ts +69 -6
  187. package/src/core/EVM/checkPermitSupport.ts +74 -0
  188. package/src/core/EVM/parseEVMErrors.ts +9 -0
  189. package/src/core/EVM/{permit2 → permits}/domain.ts +1 -7
  190. package/src/core/EVM/permits/encodeNativePermitData.ts +19 -0
  191. package/src/core/EVM/permits/encodePermit2Data.ts +41 -0
  192. package/src/core/EVM/{getNativePermit.ts → permits/getNativePermit.ts} +37 -31
  193. package/src/core/EVM/permits/getPermitTransferFromValues.ts +29 -0
  194. package/src/core/EVM/permits/signNativePermitMessage.ts +27 -0
  195. package/src/core/EVM/permits/signPermit2Message.ts +95 -0
  196. package/src/core/EVM/{permit2 → permits}/signatureTransfer.ts +19 -7
  197. package/src/core/EVM/permits/types.ts +33 -0
  198. package/src/core/EVM/permits/utils.ts +40 -0
  199. package/src/core/EVM/publicClient.ts +41 -38
  200. package/src/core/EVM/typeguards.ts +5 -2
  201. package/src/core/EVM/types.ts +15 -10
  202. package/src/core/EVM/waitForBatchTransactionReceipt.ts +7 -2
  203. package/src/core/EVM/waitForRelayedTransactionReceipt.ts +4 -4
  204. package/src/core/checkBalance.ts +2 -1
  205. package/src/core/utils.ts +1 -1
  206. package/src/errors/constants.ts +1 -0
  207. package/src/services/api.ts +62 -66
  208. package/src/version.ts +1 -1
  209. package/src/_cjs/core/EVM/getNativePermit.js.map +0 -1
  210. package/src/_cjs/core/EVM/permit2/signatureTransfer.js.map +0 -1
  211. package/src/_cjs/core/EVM/signPermitMessage.js +0 -163
  212. package/src/_cjs/core/EVM/signPermitMessage.js.map +0 -1
  213. package/src/_esm/core/EVM/getNativePermit.js.map +0 -1
  214. package/src/_esm/core/EVM/signPermitMessage.js +0 -157
  215. package/src/_esm/core/EVM/signPermitMessage.js.map +0 -1
  216. package/src/_types/core/EVM/getNativePermit.d.ts.map +0 -1
  217. package/src/_types/core/EVM/permit2/domain.d.ts +0 -8
  218. package/src/_types/core/EVM/permit2/domain.d.ts.map +0 -1
  219. package/src/_types/core/EVM/permit2/signatureTransfer.d.ts.map +0 -1
  220. package/src/_types/core/EVM/signPermitMessage.d.ts +0 -25
  221. package/src/_types/core/EVM/signPermitMessage.d.ts.map +0 -1
  222. package/src/core/EVM/signPermitMessage.ts +0 -273
  223. /package/src/_cjs/core/EVM/{permit2 → permits}/allowanceTransfer.js +0 -0
  224. /package/src/_cjs/core/EVM/{permit2 → permits}/constants.js +0 -0
  225. /package/src/_cjs/core/EVM/{permit2 → permits}/domain.js +0 -0
  226. /package/src/_cjs/core/EVM/{permit2 → permits}/signatureTransfer.js +0 -0
  227. /package/src/_esm/core/EVM/{permit2 → permits}/allowanceTransfer.js +0 -0
  228. /package/src/_esm/core/EVM/{permit2 → permits}/constants.js +0 -0
  229. /package/src/_esm/core/EVM/{permit2 → permits}/domain.js +0 -0
  230. /package/src/_types/core/EVM/{permit2 → permits}/allowanceTransfer.d.ts +0 -0
  231. /package/src/_types/core/EVM/{permit2 → permits}/constants.d.ts +0 -0
  232. /package/src/core/EVM/{permit2 → permits}/allowanceTransfer.ts +0 -0
  233. /package/src/core/EVM/{permit2 → permits}/constants.ts +0 -0
@@ -1,4 +1,4 @@
1
- import type { ExtendedChain, LiFiStep } from '@lifi/types'
1
+ import type { ExtendedChain, LiFiStep, SignedPermit } from '@lifi/types'
2
2
  import type {
3
3
  Address,
4
4
  Client,
@@ -31,11 +31,15 @@ import type {
31
31
  } from '../types.js'
32
32
  import { waitForDestinationChainTransaction } from '../waitForDestinationChainTransaction.js'
33
33
  import { checkAllowance } from './checkAllowance.js'
34
- import { getNativePermit } from './getNativePermit.js'
35
34
  import { parseEVMErrors } from './parseEVMErrors.js'
36
- import { type PermitSignature, signPermitMessage } from './signPermitMessage.js'
35
+ import { encodeNativePermitData } from './permits/encodeNativePermitData.js'
36
+ import { encodePermit2Data } from './permits/encodePermit2Data.js'
37
+ import { signPermit2Message } from './permits/signPermit2Message.js'
38
+ import type { NativePermitSignature } from './permits/types.js'
39
+ import { prettifyPermit2Data } from './permits/utils.js'
37
40
  import { switchChain } from './switchChain.js'
38
41
  import { isRelayerStep } from './typeguards.js'
42
+ import type { Call, EVMPermitStep, TransactionMethodType } from './types.js'
39
43
  import { convertExtendedChain, getMaxPriorityFeePerGas } from './utils.js'
40
44
  import {
41
45
  type WalletCallReceipt,
@@ -44,13 +48,6 @@ import {
44
48
  import { waitForRelayedTransactionReceipt } from './waitForRelayedTransactionReceipt.js'
45
49
  import { waitForTransactionReceipt } from './waitForTransactionReceipt.js'
46
50
 
47
- export type Call = {
48
- data?: Hex
49
- to?: Address
50
- value?: bigint
51
- chainId?: number
52
- }
53
-
54
51
  export interface EVMStepExecutorOptions extends StepExecutorOptions {
55
52
  client: Client
56
53
  }
@@ -123,8 +120,7 @@ export class EVMStepExecutor extends BaseStepExecutor {
123
120
  process,
124
121
  fromChain,
125
122
  toChain,
126
- atomicBatchSupported,
127
- isRelayerTransaction,
123
+ txType,
128
124
  txHash,
129
125
  isBridgeExecution,
130
126
  }: {
@@ -132,32 +128,34 @@ export class EVMStepExecutor extends BaseStepExecutor {
132
128
  process: Process
133
129
  fromChain: ExtendedChain
134
130
  toChain: ExtendedChain
135
- atomicBatchSupported: boolean
136
- isRelayerTransaction: boolean
131
+ txType: TransactionMethodType
137
132
  txHash: Hash
138
133
  isBridgeExecution: boolean
139
134
  }) => {
140
135
  let transactionReceipt: TransactionReceipt | WalletCallReceipt | undefined
141
136
 
142
- if (atomicBatchSupported) {
143
- transactionReceipt = await waitForBatchTransactionReceipt(
144
- this.client,
145
- txHash
146
- )
147
- } else if (isRelayerTransaction) {
148
- transactionReceipt = await waitForRelayedTransactionReceipt(txHash)
149
- } else {
150
- transactionReceipt = await waitForTransactionReceipt({
151
- client: this.client,
152
- chainId: fromChain.id,
153
- txHash,
154
- onReplaced: (response) => {
155
- this.statusManager.updateProcess(step, process.type, 'PENDING', {
156
- txHash: response.transaction.hash,
157
- txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
158
- })
159
- },
160
- })
137
+ switch (txType) {
138
+ case 'batched':
139
+ transactionReceipt = await waitForBatchTransactionReceipt(
140
+ this.client,
141
+ txHash
142
+ )
143
+ break
144
+ case 'relayed':
145
+ transactionReceipt = await waitForRelayedTransactionReceipt(txHash)
146
+ break
147
+ default:
148
+ transactionReceipt = await waitForTransactionReceipt({
149
+ client: this.client,
150
+ chainId: fromChain.id,
151
+ txHash,
152
+ onReplaced: (response) => {
153
+ this.statusManager.updateProcess(step, process.type, 'PENDING', {
154
+ txHash: response.transaction.hash,
155
+ txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${response.transaction.hash}`,
156
+ })
157
+ },
158
+ })
161
159
  }
162
160
 
163
161
  // Update pending process if the transaction hash from the receipt is different.
@@ -241,44 +239,23 @@ export class EVMStepExecutor extends BaseStepExecutor {
241
239
  // Check if step requires permit signature and will be used with relayer service
242
240
  const isRelayerTransaction = isRelayerStep(step)
243
241
 
244
- // Check if token requires approval
245
- // Native tokens (like ETH) don't need approval since they're not ERC20 tokens
246
- // We should support different permit types:
247
- // 1. Native permits (EIP-2612)
248
- // 2. Permit2 - Universal permit implementation by Uniswap (limited to certain chains)
249
- // 3. Standard ERC20 approval
250
- const nativePermit = await getNativePermit(
251
- this.client,
252
- fromChain,
253
- step.action.fromToken.address as Address
254
- )
255
- // Check if proxy contract is available and token supports native permits, not available for atomic batch
256
- const nativePermitSupported =
257
- nativePermit.supported &&
258
- !!fromChain.permit2Proxy &&
259
- !atomicBatchSupported &&
260
- !isRelayerTransaction && // TODO: remove once we support ERC-2771
261
- !isFromNativeToken
262
242
  // Check if chain has Permit2 contract deployed. Permit2 should not be available for atomic batch.
263
243
  const permit2Supported =
264
244
  !!fromChain.permit2 &&
265
245
  !!fromChain.permit2Proxy &&
266
246
  !atomicBatchSupported &&
267
247
  !isFromNativeToken
268
- // Token supports either native permits or Permit2
269
- const permitSupported = permit2Supported || nativePermitSupported
270
248
 
271
249
  const checkForAllowance =
272
- // No existing swap/bridgetransaction is pending
250
+ // No existing swap/bridge transaction is pending
273
251
  !existingProcess?.txHash &&
274
252
  // Token is not native (address is not zero)
275
- !isFromNativeToken &&
276
- // Token doesn't support native permits
277
- !nativePermitSupported
253
+ !isFromNativeToken
278
254
 
255
+ let nativePermitSignature: NativePermitSignature | undefined
279
256
  if (checkForAllowance) {
280
257
  // Check if token needs approval and get approval transaction or message data when available
281
- const data = await checkAllowance({
258
+ const allowanceResult = await checkAllowance({
282
259
  client: this.client,
283
260
  chain: fromChain,
284
261
  step,
@@ -289,17 +266,22 @@ export class EVMStepExecutor extends BaseStepExecutor {
289
266
  permit2Supported,
290
267
  })
291
268
 
292
- if (data) {
269
+ if (allowanceResult.status === 'BATCH_APPROVAL') {
293
270
  // Create approval transaction call
294
271
  // No value needed since we're only approving ERC20 tokens
295
272
  if (atomicBatchSupported) {
296
- calls.push({
297
- chainId: step.action.fromToken.chainId,
298
- to: step.action.fromToken.address as Address,
299
- data,
300
- })
273
+ calls.push(allowanceResult.data)
301
274
  }
302
275
  }
276
+ if (allowanceResult.status === 'NATIVE_PERMIT') {
277
+ nativePermitSignature = allowanceResult.data
278
+ }
279
+ if (
280
+ allowanceResult.status === 'ACTION_REQUIRED' &&
281
+ !this.allowUserInteraction
282
+ ) {
283
+ return step
284
+ }
303
285
  }
304
286
 
305
287
  let process = this.statusManager.findProcess(step, currentProcessType)
@@ -326,14 +308,14 @@ export class EVMStepExecutor extends BaseStepExecutor {
326
308
 
327
309
  // Wait for exiting transaction
328
310
  const txHash = process.txHash as Hash
311
+ const txType = process.txType as TransactionMethodType
329
312
 
330
313
  await this.waitForTransaction({
331
314
  step,
332
315
  process,
333
316
  fromChain,
334
317
  toChain,
335
- atomicBatchSupported,
336
- isRelayerTransaction,
318
+ txType,
337
319
  txHash,
338
320
  isBridgeExecution,
339
321
  })
@@ -341,9 +323,11 @@ export class EVMStepExecutor extends BaseStepExecutor {
341
323
  return step
342
324
  }
343
325
 
326
+ const permitRequired =
327
+ !atomicBatchSupported && !nativePermitSignature && permit2Supported
344
328
  process = this.statusManager.findOrCreateProcess({
345
329
  step,
346
- type: permitSupported ? 'PERMIT' : currentProcessType,
330
+ type: permitRequired ? 'PERMIT' : currentProcessType,
347
331
  status: 'STARTED',
348
332
  })
349
333
 
@@ -353,7 +337,7 @@ export class EVMStepExecutor extends BaseStepExecutor {
353
337
  // Create new transaction request
354
338
  if (!step.transactionRequest) {
355
339
  const { execution, ...stepBase } = step
356
- let updatedStep: LiFiStep
340
+ let updatedStep: LiFiStep | EVMPermitStep
357
341
  if (isRelayerTransaction) {
358
342
  const updatedRelayedStep = await getRelayerQuote({
359
343
  fromChain: stepBase.action.fromChainId,
@@ -367,8 +351,8 @@ export class EVMStepExecutor extends BaseStepExecutor {
367
351
  allowBridges: [stepBase.tool],
368
352
  })
369
353
  updatedStep = {
370
- ...updatedRelayedStep.data.quote.step,
371
- ...updatedRelayedStep.data.quote,
354
+ ...updatedRelayedStep.quote,
355
+ permits: updatedRelayedStep.permits,
372
356
  id: stepBase.id,
373
357
  }
374
358
  } else {
@@ -448,7 +432,7 @@ export class EVMStepExecutor extends BaseStepExecutor {
448
432
  }
449
433
 
450
434
  let txHash: Hash
451
- let isTransactionRelayed = false
435
+ let txType: TransactionMethodType = 'standard'
452
436
 
453
437
  if (atomicBatchSupported) {
454
438
  const transferCall: Call = {
@@ -468,100 +452,154 @@ export class EVMStepExecutor extends BaseStepExecutor {
468
452
  account: this.client.account!,
469
453
  calls,
470
454
  })) as Address
455
+ txType = 'batched'
456
+ } else if (isRelayerTransaction) {
457
+ const permitWitnessTransferFromData = step.permits.find(
458
+ (p) => p.permitType === 'PermitWitnessTransferFrom'
459
+ )
460
+
461
+ if (!permitWitnessTransferFromData) {
462
+ throw new TransactionError(
463
+ LiFiErrorCode.TransactionUnprepared,
464
+ 'Unable to prepare transaction. Permit data for transfer is not found.'
465
+ )
466
+ }
467
+
468
+ const permit2Signature = await signPermit2Message({
469
+ client: this.client,
470
+ chain: fromChain,
471
+ tokenAddress: step.action.fromToken.address as Address,
472
+ amount: BigInt(step.action.fromAmount),
473
+ data: transactionRequest.data as Hex,
474
+ permitData: prettifyPermit2Data(
475
+ permitWitnessTransferFromData.permitData
476
+ ),
477
+ witness: true,
478
+ })
479
+
480
+ this.statusManager.updateProcess(step, process.type, 'DONE')
481
+
482
+ process = this.statusManager.findOrCreateProcess({
483
+ step,
484
+ type: currentProcessType,
485
+ status: 'PENDING',
486
+ })
487
+
488
+ const signedPermits: SignedPermit[] = [
489
+ {
490
+ permitType: 'PermitWitnessTransferFrom',
491
+ permit: permit2Signature.values,
492
+ signature: permit2Signature.signature,
493
+ },
494
+ ]
495
+ // Add native permit if available as first element, order is important
496
+ if (nativePermitSignature) {
497
+ signedPermits.unshift({
498
+ permitType: 'Permit',
499
+ permit: nativePermitSignature.values,
500
+ signature: nativePermitSignature.signature,
501
+ })
502
+ }
503
+
504
+ const relayedTransaction = await relayTransaction({
505
+ tokenOwner: this.client.account!.address,
506
+ chainId: fromChain.id,
507
+ permits: signedPermits,
508
+ callData: transactionRequest.data! as Hex,
509
+ })
510
+ txHash = relayedTransaction.taskId as Hash
511
+ txType = 'relayed'
471
512
  } else {
472
- let permitSignature: PermitSignature | undefined
473
- if (permitSupported) {
474
- permitSignature = await signPermitMessage(this.client, {
475
- transactionRequest,
513
+ if (nativePermitSignature) {
514
+ transactionRequest.data = encodeNativePermitData(
515
+ step.action.fromToken.address as Address,
516
+ BigInt(step.action.fromAmount),
517
+ nativePermitSignature.values.deadline,
518
+ nativePermitSignature.signature,
519
+ transactionRequest.data as Hex
520
+ )
521
+ } else if (permit2Supported) {
522
+ const permit2Signature = await signPermit2Message({
523
+ client: this.client,
476
524
  chain: fromChain,
477
525
  tokenAddress: step.action.fromToken.address as Address,
478
526
  amount: BigInt(step.action.fromAmount),
479
- nativePermit,
480
- permitData: isRelayerTransaction ? step.permitData : undefined,
481
- useWitness: isRelayerTransaction,
527
+ data: transactionRequest.data as Hex,
482
528
  })
483
- transactionRequest.to = fromChain.permit2Proxy
484
529
  this.statusManager.updateProcess(step, process.type, 'DONE')
485
- }
486
- if (isRelayerTransaction && permitSignature) {
530
+
487
531
  process = this.statusManager.findOrCreateProcess({
488
532
  step,
489
533
  type: currentProcessType,
490
534
  status: 'PENDING',
491
535
  })
492
- const relayedTransaction = await relayTransaction({
493
- tokenOwner: this.client.account!.address,
494
- chainId: fromChain.id,
495
- permit: step.permit,
496
- witness: step.witness,
497
- signedPermitData: permitSignature.signature,
498
- callData: transactionRequest.data!,
499
- })
500
- txHash = relayedTransaction.data.taskId
501
- isTransactionRelayed = true
502
- } else {
503
- process = this.statusManager.findOrCreateProcess({
504
- step,
505
- type: currentProcessType,
506
- status: 'STARTED',
507
- })
508
- if (permitSignature) {
509
- // If we have a permit signature, we need to use updated data
510
- transactionRequest.data = permitSignature.data
511
- try {
512
- // Try to re-estimate the gas due to additional Permit data
513
- const estimatedGas = await estimateGas(this.client, {
514
- account: this.client.account!,
515
- to: transactionRequest.to as Address,
516
- data: transactionRequest.data as Hex,
517
- value: transactionRequest.value,
518
- })
519
- transactionRequest.gas =
520
- transactionRequest.gas && transactionRequest.gas > estimatedGas
521
- ? transactionRequest.gas
522
- : estimatedGas
523
- } catch {
524
- // Let the wallet estimate the gas in case of failure
525
- transactionRequest.gas = undefined
526
- }
527
- }
528
- process = this.statusManager.updateProcess(
529
- step,
530
- process.type,
531
- 'ACTION_REQUIRED'
536
+ transactionRequest.data = encodePermit2Data(
537
+ step.action.fromToken.address as Address,
538
+ BigInt(step.action.fromAmount),
539
+ permit2Signature.values.nonce,
540
+ permit2Signature.values.deadline,
541
+ transactionRequest.data as Hex,
542
+ permit2Signature.signature
532
543
  )
533
- txHash = await getAction(
534
- this.client,
535
- sendTransaction,
536
- 'sendTransaction'
537
- )({
538
- to: transactionRequest.to as Address,
539
- account: this.client.account!,
540
- data: transactionRequest.data as Hex,
541
- value: transactionRequest.value,
542
- gas: transactionRequest.gas,
543
- gasPrice: transactionRequest.gasPrice,
544
- maxFeePerGas: transactionRequest.maxFeePerGas,
545
- maxPriorityFeePerGas: transactionRequest.maxPriorityFeePerGas,
546
- chain: convertExtendedChain(fromChain),
547
- } as SendTransactionParameters)
548
544
  }
545
+
546
+ if (nativePermitSignature || permit2Supported) {
547
+ try {
548
+ // Target address should be the Permit2 proxy contract in case of native permit or Permit2
549
+ transactionRequest.to = fromChain.permit2Proxy
550
+ // Try to re-estimate the gas due to additional Permit data
551
+ const estimatedGas = await estimateGas(this.client, {
552
+ account: this.client.account!,
553
+ to: transactionRequest.to as Address,
554
+ data: transactionRequest.data as Hex,
555
+ value: transactionRequest.value,
556
+ })
557
+ transactionRequest.gas =
558
+ transactionRequest.gas && transactionRequest.gas > estimatedGas
559
+ ? transactionRequest.gas
560
+ : estimatedGas
561
+ } catch {
562
+ // Let the wallet estimate the gas in case of failure
563
+ transactionRequest.gas = undefined
564
+ } finally {
565
+ this.statusManager.updateProcess(step, process.type, 'DONE')
566
+ }
567
+ }
568
+ process = this.statusManager.updateProcess(
569
+ step,
570
+ process.type,
571
+ 'ACTION_REQUIRED'
572
+ )
573
+ txHash = await getAction(
574
+ this.client,
575
+ sendTransaction,
576
+ 'sendTransaction'
577
+ )({
578
+ to: transactionRequest.to as Address,
579
+ account: this.client.account!,
580
+ data: transactionRequest.data as Hex,
581
+ value: transactionRequest.value,
582
+ gas: transactionRequest.gas,
583
+ gasPrice: transactionRequest.gasPrice,
584
+ maxFeePerGas: transactionRequest.maxFeePerGas,
585
+ maxPriorityFeePerGas: transactionRequest.maxPriorityFeePerGas,
586
+ chain: convertExtendedChain(fromChain),
587
+ } as SendTransactionParameters)
549
588
  }
589
+
550
590
  process = this.statusManager.updateProcess(
551
591
  step,
552
592
  process.type,
553
593
  'PENDING',
554
- // When atomic batch is supported, txHash represents the batch hash rather than an individual transaction hash at this point
555
- atomicBatchSupported
556
- ? {
557
- atomicBatchSupported,
558
- }
559
- : isTransactionRelayed
560
- ? undefined
561
- : {
562
- txHash: txHash,
563
- txLink: `${fromChain.metamask.blockExplorerUrls[0]}tx/${txHash}`,
564
- }
594
+ // When atomic batch or relayer are supported, txHash represents the batch hash or taskId rather than an individual transaction hash
595
+ {
596
+ txHash,
597
+ txType,
598
+ txLink:
599
+ txType === 'standard'
600
+ ? `${fromChain.metamask.blockExplorerUrls[0]}tx/${txHash}`
601
+ : undefined,
602
+ }
565
603
  )
566
604
 
567
605
  await this.waitForTransaction({
@@ -569,9 +607,8 @@ export class EVMStepExecutor extends BaseStepExecutor {
569
607
  process,
570
608
  fromChain,
571
609
  toChain,
572
- atomicBatchSupported,
573
- isRelayerTransaction,
574
610
  txHash,
611
+ txType,
575
612
  isBridgeExecution,
576
613
  })
577
614
 
@@ -5,7 +5,16 @@ import type { StatusManager } from '../StatusManager.js'
5
5
  import type { ExecutionOptions, Process, ProcessType } from '../types.js'
6
6
  import { getAllowance } from './getAllowance.js'
7
7
  import { parseEVMErrors } from './parseEVMErrors.js'
8
+ import { getNativePermit } from './permits/getNativePermit.js'
9
+ import { signNativePermitMessage } from './permits/signNativePermitMessage.js'
10
+ import type {
11
+ NativePermitData,
12
+ NativePermitSignature,
13
+ } from './permits/types.js'
14
+ import { prettifyNativePermitData } from './permits/utils.js'
8
15
  import { setAllowance } from './setAllowance.js'
16
+ import { isRelayerStep } from './typeguards.js'
17
+ import type { Call } from './types.js'
9
18
  import { waitForTransactionReceipt } from './waitForTransactionReceipt.js'
10
19
 
11
20
  export type CheckAllowanceParams = {
@@ -19,6 +28,19 @@ export type CheckAllowanceParams = {
19
28
  permit2Supported?: boolean
20
29
  }
21
30
 
31
+ export type AllowanceResult =
32
+ | {
33
+ status: 'ACTION_REQUIRED' | 'DONE'
34
+ }
35
+ | {
36
+ status: 'BATCH_APPROVAL'
37
+ data: Call
38
+ }
39
+ | {
40
+ status: 'NATIVE_PERMIT'
41
+ data: NativePermitSignature
42
+ }
43
+
22
44
  export const checkAllowance = async ({
23
45
  client,
24
46
  chain,
@@ -28,7 +50,7 @@ export const checkAllowance = async ({
28
50
  allowUserInteraction = false,
29
51
  atomicBatchSupported = false,
30
52
  permit2Supported = false,
31
- }: CheckAllowanceParams): Promise<Hash | void> => {
53
+ }: CheckAllowanceParams): Promise<AllowanceResult> => {
32
54
  // Find existing or create new allowance process
33
55
  const allowanceProcess: Process = statusManager.findOrCreateProcess({
34
56
  step,
@@ -47,7 +69,7 @@ export const checkAllowance = async ({
47
69
  chain,
48
70
  statusManager
49
71
  )
50
- return
72
+ return { status: 'DONE' }
51
73
  }
52
74
 
53
75
  // Start new allowance check
@@ -68,15 +90,47 @@ export const checkAllowance = async ({
68
90
  // Return early if already approved
69
91
  if (fromAmount <= approved) {
70
92
  statusManager.updateProcess(step, allowanceProcess.type, 'DONE')
71
- return
93
+ return { status: 'DONE' }
72
94
  }
73
95
 
74
- if (!allowUserInteraction) {
75
- return
96
+ const isRelayerTransaction = isRelayerStep(step)
97
+
98
+ let nativePermitData: NativePermitData | undefined
99
+ if (isRelayerTransaction) {
100
+ const permitData = step.permits.find(
101
+ (p) => p.permitType === 'Permit'
102
+ )?.permitData
103
+ if (permitData) {
104
+ nativePermitData = prettifyNativePermitData(permitData)
105
+ }
106
+ } else {
107
+ nativePermitData = await getNativePermit(
108
+ client,
109
+ chain,
110
+ step.action.fromToken.address as Address,
111
+ fromAmount
112
+ )
76
113
  }
77
114
 
78
115
  statusManager.updateProcess(step, allowanceProcess.type, 'ACTION_REQUIRED')
79
116
 
117
+ if (!allowUserInteraction) {
118
+ return { status: 'ACTION_REQUIRED' }
119
+ }
120
+
121
+ // Check if proxy contract is available and token supports native permits, not available for atomic batch
122
+ const nativePermitSupported =
123
+ !!nativePermitData && !!chain.permit2Proxy && !atomicBatchSupported
124
+
125
+ if (nativePermitSupported && nativePermitData) {
126
+ const nativePermitSignature = await signNativePermitMessage(
127
+ client,
128
+ nativePermitData
129
+ )
130
+ statusManager.updateProcess(step, allowanceProcess.type, 'DONE')
131
+ return { status: 'NATIVE_PERMIT', data: nativePermitSignature }
132
+ }
133
+
80
134
  // Set new allowance
81
135
  const approveAmount = permit2Supported ? MaxUint256 : fromAmount
82
136
  const approveTxHash = await setAllowance(
@@ -90,7 +144,14 @@ export const checkAllowance = async ({
90
144
 
91
145
  if (atomicBatchSupported) {
92
146
  statusManager.updateProcess(step, allowanceProcess.type, 'DONE')
93
- return approveTxHash
147
+ return {
148
+ status: 'BATCH_APPROVAL',
149
+ data: {
150
+ to: step.action.fromToken.address as Address,
151
+ data: approveTxHash,
152
+ chainId: step.action.fromToken.chainId,
153
+ },
154
+ }
94
155
  }
95
156
 
96
157
  await waitForApprovalTransaction(
@@ -101,6 +162,8 @@ export const checkAllowance = async ({
101
162
  chain,
102
163
  statusManager
103
164
  )
165
+
166
+ return { status: 'DONE' }
104
167
  } catch (e: any) {
105
168
  const error = await parseEVMErrors(e, step, allowanceProcess)
106
169
  statusManager.updateProcess(step, allowanceProcess.type, 'FAILED', {
@@ -0,0 +1,74 @@
1
+ import type { ExtendedChain } from '@lifi/types'
2
+ import { ChainType } from '@lifi/types'
3
+ import type { Address } from 'viem'
4
+ import { config } from '../../config.js'
5
+ import { getAllowance } from './getAllowance.js'
6
+ import { getNativePermit } from './permits/getNativePermit.js'
7
+ import type { NativePermitData } from './permits/types.js'
8
+ import { getPublicClient } from './publicClient.js'
9
+ import type { EVMProvider } from './types.js'
10
+
11
+ export type PermitSupport = {
12
+ /** Whether the token supports EIP-2612 native permits */
13
+ nativePermitSupported: boolean
14
+ /** Whether Permit2 is available and has sufficient allowance */
15
+ permit2AllowanceSufficient: boolean
16
+ }
17
+
18
+ /**
19
+ * Checks what permit types are supported for a token on a specific chain.
20
+ * Checks in order:
21
+ * 1. Native permit (EIP-2612) support
22
+ * 2. Permit2 availability and allowance
23
+ *
24
+ * @param chain - The chain to check permit support on
25
+ * @param tokenAddress - The token address to check
26
+ * @param ownerAddress - The address that would sign the permit
27
+ * @param amount - The amount to check allowance against for Permit2
28
+ * @returns Object indicating which permit types are supported
29
+ */
30
+ export const checkPermitSupport = async ({
31
+ chain,
32
+ tokenAddress,
33
+ ownerAddress,
34
+ amount,
35
+ }: {
36
+ chain: ExtendedChain
37
+ tokenAddress: Address
38
+ ownerAddress: Address
39
+ amount: bigint
40
+ }): Promise<PermitSupport> => {
41
+ const provider = config.getProvider(ChainType.EVM) as EVMProvider | undefined
42
+
43
+ let client = await provider?.getWalletClient?.()
44
+
45
+ if (!client) {
46
+ client = await getPublicClient(chain.id)
47
+ }
48
+
49
+ let nativePermit: NativePermitData | undefined
50
+ // Try with wallet client first, fallback to public client
51
+ try {
52
+ nativePermit = await getNativePermit(client, chain, tokenAddress, amount)
53
+ } catch {
54
+ client = await getPublicClient(chain.id)
55
+ nativePermit = await getNativePermit(client, chain, tokenAddress, amount)
56
+ }
57
+
58
+ let permit2Allowance: bigint | undefined
59
+ // Check Permit2 allowance if available on chain
60
+ if (chain.permit2) {
61
+ permit2Allowance = await getAllowance(
62
+ chain.id,
63
+ tokenAddress,
64
+ ownerAddress,
65
+ chain.permit2 as Address
66
+ )
67
+ }
68
+
69
+ return {
70
+ nativePermitSupported: !!nativePermit,
71
+ permit2AllowanceSufficient:
72
+ !!permit2Allowance && permit2Allowance >= amount,
73
+ }
74
+ }