@openocean.finance/widget 1.0.27 → 1.0.29

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 (110) hide show
  1. package/dist/esm/components/AmountInput/AmountInputEndAdornment.js +46 -39
  2. package/dist/esm/components/AmountInput/AmountInputEndAdornment.js.map +1 -1
  3. package/dist/esm/components/Messages/WarningMessages.js +2 -2
  4. package/dist/esm/components/Messages/WarningMessages.js.map +1 -1
  5. package/dist/esm/components/Step/Step.js +37 -29
  6. package/dist/esm/components/Step/Step.js.map +1 -1
  7. package/dist/esm/components/TransactionDetails.js +2 -5
  8. package/dist/esm/components/TransactionDetails.js.map +1 -1
  9. package/dist/esm/config/version.d.ts +1 -1
  10. package/dist/esm/config/version.js +1 -1
  11. package/dist/esm/cross/adapters/AcrossAdapter.d.ts +15 -0
  12. package/dist/esm/cross/adapters/AcrossAdapter.js +166 -0
  13. package/dist/esm/cross/adapters/AcrossAdapter.js.map +1 -0
  14. package/dist/esm/cross/adapters/BaseSwapAdapter.d.ts +107 -0
  15. package/dist/esm/cross/adapters/BaseSwapAdapter.js +44 -0
  16. package/dist/esm/cross/adapters/BaseSwapAdapter.js.map +1 -0
  17. package/dist/esm/cross/adapters/DebridgeAdapter.d.ts +20 -0
  18. package/dist/esm/cross/adapters/DebridgeAdapter.js +264 -0
  19. package/dist/esm/cross/adapters/DebridgeAdapter.js.map +1 -0
  20. package/dist/esm/cross/adapters/LifiAdapter.d.ts +19 -0
  21. package/dist/esm/cross/adapters/LifiAdapter.js +169 -0
  22. package/dist/esm/cross/adapters/LifiAdapter.js.map +1 -0
  23. package/dist/esm/cross/adapters/MayanAdapter.d.ts +14 -0
  24. package/dist/esm/cross/adapters/MayanAdapter.js +119 -0
  25. package/dist/esm/cross/adapters/MayanAdapter.js.map +1 -0
  26. package/dist/esm/cross/adapters/NearIntentsAdapter.d.ts +21 -0
  27. package/dist/esm/cross/adapters/NearIntentsAdapter.js +425 -0
  28. package/dist/esm/cross/adapters/NearIntentsAdapter.js.map +1 -0
  29. package/dist/esm/cross/adapters/OptimexAdapter.d.ts +19 -0
  30. package/dist/esm/cross/adapters/OptimexAdapter.js +216 -0
  31. package/dist/esm/cross/adapters/OptimexAdapter.js.map +1 -0
  32. package/dist/esm/cross/adapters/OrbiterAdapter.d.ts +20 -0
  33. package/dist/esm/cross/adapters/OrbiterAdapter.js +213 -0
  34. package/dist/esm/cross/adapters/OrbiterAdapter.js.map +1 -0
  35. package/dist/esm/cross/adapters/RelayAdapter.d.ts +14 -0
  36. package/dist/esm/cross/adapters/RelayAdapter.js +171 -0
  37. package/dist/esm/cross/adapters/RelayAdapter.js.map +1 -0
  38. package/dist/esm/cross/adapters/SymbiosisAdapter.d.ts +14 -0
  39. package/dist/esm/cross/adapters/SymbiosisAdapter.js +120 -0
  40. package/dist/esm/cross/adapters/SymbiosisAdapter.js.map +1 -0
  41. package/dist/esm/cross/adapters/XYFinanceAdapter.d.ts +14 -0
  42. package/dist/esm/cross/adapters/XYFinanceAdapter.js +177 -0
  43. package/dist/esm/cross/adapters/XYFinanceAdapter.js.map +1 -0
  44. package/dist/esm/cross/adapters/index.d.ts +2 -0
  45. package/dist/esm/cross/adapters/index.js +10 -0
  46. package/dist/esm/cross/adapters/index.js.map +1 -0
  47. package/dist/esm/cross/constants/index.d.ts +202 -0
  48. package/dist/esm/cross/constants/index.js +183 -0
  49. package/dist/esm/cross/constants/index.js.map +1 -0
  50. package/dist/esm/cross/crossChainQuote.d.ts +25 -0
  51. package/dist/esm/cross/crossChainQuote.js +127 -0
  52. package/dist/esm/cross/crossChainQuote.js.map +1 -0
  53. package/dist/esm/cross/factory.d.ts +9 -0
  54. package/dist/esm/cross/factory.js +125 -0
  55. package/dist/esm/cross/factory.js.map +1 -0
  56. package/dist/esm/cross/registry.d.ts +12 -0
  57. package/dist/esm/cross/registry.js +52 -0
  58. package/dist/esm/cross/registry.js.map +1 -0
  59. package/dist/esm/hooks/useChain.d.ts +1 -1
  60. package/dist/esm/hooks/useGasRefuel.d.ts +1 -1
  61. package/dist/esm/hooks/useGasSufficiencyBridge.js +1 -2
  62. package/dist/esm/hooks/useGasSufficiencyBridge.js.map +1 -1
  63. package/dist/esm/hooks/useRouteExecution.js +2 -1
  64. package/dist/esm/hooks/useRouteExecution.js.map +1 -1
  65. package/dist/esm/hooks/useRoutes.js +50 -32
  66. package/dist/esm/hooks/useRoutes.js.map +1 -1
  67. package/dist/esm/hooks/useSettingMonitor.js +1 -0
  68. package/dist/esm/hooks/useSettingMonitor.js.map +1 -1
  69. package/dist/esm/hooks/useTokenAddressBalance.d.ts +1 -1
  70. package/dist/esm/hooks/useTokenPrice.js +4 -2
  71. package/dist/esm/hooks/useTokenPrice.js.map +1 -1
  72. package/dist/esm/hooks/useTokens.d.ts +1 -1
  73. package/dist/esm/services/ExecuteRoute.js +217 -195
  74. package/dist/esm/services/ExecuteRoute.js.map +1 -1
  75. package/dist/esm/stores/form/useFieldController.d.ts +1 -1
  76. package/dist/esm/stores/routes/createRouteExecutionStore.js +6 -3
  77. package/dist/esm/stores/routes/createRouteExecutionStore.js.map +1 -1
  78. package/dist/esm/stores/routes/useSetExecutableRoute.d.ts +1 -1
  79. package/dist/esm/types/widget.d.ts +3 -0
  80. package/dist/tsconfig.tsbuildinfo +1 -0
  81. package/package.json +14 -4
  82. package/src/components/AmountInput/AmountInputEndAdornment.tsx +46 -46
  83. package/src/components/Messages/WarningMessages.tsx +7 -2
  84. package/src/components/Step/Step.tsx +37 -31
  85. package/src/components/TransactionDetails.tsx +10 -11
  86. package/src/config/version.ts +1 -1
  87. package/src/cross/adapters/AcrossAdapter.ts +193 -0
  88. package/src/cross/adapters/BaseSwapAdapter.ts +173 -0
  89. package/src/cross/adapters/DebridgeAdapter.ts +375 -0
  90. package/src/cross/adapters/LifiAdapter.ts +213 -0
  91. package/src/cross/adapters/MayanAdapter.ts +179 -0
  92. package/src/cross/adapters/NearIntentsAdapter.ts +539 -0
  93. package/src/cross/adapters/OptimexAdapter.ts +273 -0
  94. package/src/cross/adapters/OrbiterAdapter.ts +270 -0
  95. package/src/cross/adapters/RelayAdapter.ts +248 -0
  96. package/src/cross/adapters/SymbiosisAdapter.ts +144 -0
  97. package/src/cross/adapters/XYFinanceAdapter.ts +213 -0
  98. package/src/cross/adapters/index.ts +9 -0
  99. package/src/cross/constants/index.ts +223 -0
  100. package/src/cross/crossChainQuote.ts +181 -0
  101. package/src/cross/factory.ts +145 -0
  102. package/src/cross/registry.ts +65 -0
  103. package/src/hooks/useGasSufficiencyBridge.ts +1 -3
  104. package/src/hooks/useRouteExecution.ts +2 -1
  105. package/src/hooks/useRoutes.ts +64 -43
  106. package/src/hooks/useSettingMonitor.ts +1 -1
  107. package/src/hooks/useTokenPrice.ts +5 -3
  108. package/src/services/ExecuteRoute.ts +305 -282
  109. package/src/stores/routes/createRouteExecutionStore.ts +13 -4
  110. package/src/types/widget.ts +3 -0
@@ -6,116 +6,116 @@ import type {
6
6
  Route,
7
7
  } from '@openocean.finance/widget-sdk'
8
8
  import { Connection, Transaction, VersionedTransaction } from '@solana/web3.js'
9
- import type { Config } from 'wagmi'
9
+ import { ethers } from 'ethers'
10
10
  import { getPublicClient, getWalletClient } from 'wagmi/actions'
11
- import { sendAndConfirmSolanaTransaction } from './SendAndConfirmSolanaTransaction.js'
11
+ import { bridgeExecuteSwap } from '../cross/crossChainQuote.js'
12
12
  import { useSettingsStore } from '../stores/settings/useSettingsStore.js'
13
- import { ethers } from 'ethers'
13
+ import { sendAndConfirmSolanaTransaction } from './SendAndConfirmSolanaTransaction.js'
14
14
 
15
15
  const OpenOceanABI = [
16
16
  {
17
- "inputs": [
17
+ inputs: [
18
+ {
19
+ internalType: 'contract IOpenOceanCaller',
20
+ name: 'caller',
21
+ type: 'address',
22
+ },
23
+ {
24
+ components: [
18
25
  {
19
- "internalType": "contract IOpenOceanCaller",
20
- "name": "caller",
21
- "type": "address"
26
+ internalType: 'contract IERC20',
27
+ name: 'srcToken',
28
+ type: 'address',
22
29
  },
23
30
  {
24
- "components": [
25
- {
26
- "internalType": "contract IERC20",
27
- "name": "srcToken",
28
- "type": "address"
29
- },
30
- {
31
- "internalType": "contract IERC20",
32
- "name": "dstToken",
33
- "type": "address"
34
- },
35
- {
36
- "internalType": "address",
37
- "name": "srcReceiver",
38
- "type": "address"
39
- },
40
- {
41
- "internalType": "address",
42
- "name": "dstReceiver",
43
- "type": "address"
44
- },
45
- {
46
- "internalType": "uint256",
47
- "name": "amount",
48
- "type": "uint256"
49
- },
50
- {
51
- "internalType": "uint256",
52
- "name": "minReturnAmount",
53
- "type": "uint256"
54
- },
55
- {
56
- "internalType": "uint256",
57
- "name": "guaranteedAmount",
58
- "type": "uint256"
59
- },
60
- {
61
- "internalType": "uint256",
62
- "name": "flags",
63
- "type": "uint256"
64
- },
65
- {
66
- "internalType": "address",
67
- "name": "referrer",
68
- "type": "address"
69
- },
70
- {
71
- "internalType": "bytes",
72
- "name": "permit",
73
- "type": "bytes"
74
- }
75
- ],
76
- "internalType": "struct OpenOceanExchange.SwapDescription",
77
- "name": "desc",
78
- "type": "tuple"
31
+ internalType: 'contract IERC20',
32
+ name: 'dstToken',
33
+ type: 'address',
79
34
  },
80
35
  {
81
- "components": [
82
- {
83
- "internalType": "uint256",
84
- "name": "target",
85
- "type": "uint256"
86
- },
87
- {
88
- "internalType": "uint256",
89
- "name": "gasLimit",
90
- "type": "uint256"
91
- },
92
- {
93
- "internalType": "uint256",
94
- "name": "value",
95
- "type": "uint256"
96
- },
97
- {
98
- "internalType": "bytes",
99
- "name": "data",
100
- "type": "bytes"
101
- }
102
- ],
103
- "internalType": "struct IOpenOceanCaller.CallDescription[]",
104
- "name": "calls",
105
- "type": "tuple[]"
106
- }
107
- ],
108
- "name": "swap",
109
- "outputs": [
36
+ internalType: 'address',
37
+ name: 'srcReceiver',
38
+ type: 'address',
39
+ },
110
40
  {
111
- "internalType": "uint256",
112
- "name": "returnAmount",
113
- "type": "uint256"
114
- }
115
- ],
116
- "stateMutability": "payable",
117
- "type": "function"
118
- }
41
+ internalType: 'address',
42
+ name: 'dstReceiver',
43
+ type: 'address',
44
+ },
45
+ {
46
+ internalType: 'uint256',
47
+ name: 'amount',
48
+ type: 'uint256',
49
+ },
50
+ {
51
+ internalType: 'uint256',
52
+ name: 'minReturnAmount',
53
+ type: 'uint256',
54
+ },
55
+ {
56
+ internalType: 'uint256',
57
+ name: 'guaranteedAmount',
58
+ type: 'uint256',
59
+ },
60
+ {
61
+ internalType: 'uint256',
62
+ name: 'flags',
63
+ type: 'uint256',
64
+ },
65
+ {
66
+ internalType: 'address',
67
+ name: 'referrer',
68
+ type: 'address',
69
+ },
70
+ {
71
+ internalType: 'bytes',
72
+ name: 'permit',
73
+ type: 'bytes',
74
+ },
75
+ ],
76
+ internalType: 'struct OpenOceanExchange.SwapDescription',
77
+ name: 'desc',
78
+ type: 'tuple',
79
+ },
80
+ {
81
+ components: [
82
+ {
83
+ internalType: 'uint256',
84
+ name: 'target',
85
+ type: 'uint256',
86
+ },
87
+ {
88
+ internalType: 'uint256',
89
+ name: 'gasLimit',
90
+ type: 'uint256',
91
+ },
92
+ {
93
+ internalType: 'uint256',
94
+ name: 'value',
95
+ type: 'uint256',
96
+ },
97
+ {
98
+ internalType: 'bytes',
99
+ name: 'data',
100
+ type: 'bytes',
101
+ },
102
+ ],
103
+ internalType: 'struct IOpenOceanCaller.CallDescription[]',
104
+ name: 'calls',
105
+ type: 'tuple[]',
106
+ },
107
+ ],
108
+ name: 'swap',
109
+ outputs: [
110
+ {
111
+ internalType: 'uint256',
112
+ name: 'returnAmount',
113
+ type: 'uint256',
114
+ },
115
+ ],
116
+ stateMutability: 'payable',
117
+ type: 'function',
118
+ },
119
119
  ]
120
120
 
121
121
  // Add helper function for handling hexadecimal conversion
@@ -124,6 +124,121 @@ function hexToUint8Array(hexString: string): Uint8Array {
124
124
  return new Uint8Array(pairs.map((s) => Number.parseInt(s, 16)))
125
125
  }
126
126
 
127
+ /**
128
+ * Convert amount with precision to actual amount
129
+ * @param amount Amount with precision
130
+ * @param decimals Precision
131
+ * @returns Actual amount
132
+ */
133
+ function decimals2Amount(amount: string | number, decimals = 18): number {
134
+ return Number(amount) / 10 ** decimals
135
+ }
136
+
137
+ /**
138
+ * Swap response type
139
+ */
140
+ interface SwapResponse {
141
+ inAmount?: string
142
+ inToken?: {
143
+ decimals?: number
144
+ price?: string | number
145
+ priceUSD?: string | number
146
+ address?: string
147
+ }
148
+ data?: string
149
+ from?: string
150
+ to?: string
151
+ value?: string
152
+ minOutAmount?: string
153
+ }
154
+
155
+ /**
156
+ * Adjust transaction parameters based on dynamic slippage to provide MEV protection
157
+ */
158
+ async function swapQuoteMEV(
159
+ response: SwapResponse,
160
+ options?: { publicClient?: any }
161
+ ): Promise<SwapResponse> {
162
+ try {
163
+ const inAmount = response?.inAmount
164
+ const inTokenDecimals = response?.inToken?.decimals || 18
165
+ const inTokenPrice = Number(response?.inToken?.priceUSD || 0)
166
+ const amount = decimals2Amount(inAmount, inTokenDecimals) * inTokenPrice
167
+ if (amount < 1) {
168
+ return response
169
+ }
170
+ const { publicClient } = options
171
+ const OPENOCEAN_CONTRACT = new ethers.Contract(
172
+ '0x6352a56caadC4F1E25CD6c75970Fa768A3304e64',
173
+ OpenOceanABI
174
+ )
175
+ if (
176
+ ethers.hexlify(ethers.getBytes(response?.data || '0x').slice(0, 4)) !==
177
+ OPENOCEAN_CONTRACT.interface.getFunction('swap').selector
178
+ ) {
179
+ return response
180
+ }
181
+ const oldCallData = OPENOCEAN_CONTRACT.interface.decodeFunctionData(
182
+ 'swap',
183
+ response?.data
184
+ )
185
+ const callData = [...oldCallData]
186
+ callData[1] = [...oldCallData[1]]
187
+ const minOutAmount = BigInt(callData[1][5] || 0)
188
+ const outAmount = BigInt(callData[1][6] || 0)
189
+ const slippageAmount = outAmount - minOutAmount
190
+
191
+ const minOutAmounts = await Promise.all(
192
+ [1, 2, 3].map(async (i) => {
193
+ const mockMinOutAmount =
194
+ minOutAmount + (slippageAmount / 4n) * BigInt(i)
195
+ callData[1][5] = mockMinOutAmount
196
+ const params = {
197
+ from: response?.from as `0x${string}`,
198
+ to: response?.to as `0x${string}`,
199
+ data: OPENOCEAN_CONTRACT.interface.encodeFunctionData(
200
+ 'swap',
201
+ callData
202
+ ) as `0x${string}`,
203
+ value: BigInt(response?.value || '0'),
204
+ }
205
+ try {
206
+ await publicClient.estimateGas(params)
207
+ return mockMinOutAmount
208
+ } catch (error) {
209
+ console.error('Failed to estimate gas:', error)
210
+ return undefined
211
+ }
212
+ })
213
+ )
214
+ let [min1, min2] = minOutAmounts
215
+ .filter((value) => value !== undefined)
216
+ .sort((a, b) => (BigInt(b || 0) > BigInt(a || 0) ? 1 : -1))
217
+ .slice(0, 2)
218
+ min1 = min1 ?? minOutAmount
219
+ min2 = min2 ?? minOutAmount
220
+
221
+ const randomFactor = BigInt(Math.floor(Math.random() * 10000))
222
+ const minOutAmountDiff = BigInt(min1 || 0) - BigInt(min2 || 0)
223
+ const finalMinOutAmount =
224
+ BigInt(min2 || 0) + (minOutAmountDiff * randomFactor) / BigInt(10000)
225
+
226
+ if (finalMinOutAmount < minOutAmount) {
227
+ return response
228
+ }
229
+ callData[1][5] = finalMinOutAmount
230
+ const finalCallData = OPENOCEAN_CONTRACT.interface.encodeFunctionData(
231
+ 'swap',
232
+ callData
233
+ )
234
+ response.minOutAmount = finalMinOutAmount.toString()
235
+ response.data = finalCallData
236
+ return response
237
+ } catch {
238
+ return response
239
+ }
240
+ }
241
+
127
242
  interface ExecuteRouteOptions {
128
243
  updateRouteHook?: (route: Route) => void
129
244
  acceptExchangeRateUpdateHook?: (params: any) => Promise<boolean>
@@ -136,6 +251,7 @@ interface ExecuteRouteOptions {
136
251
  }
137
252
 
138
253
  interface ExtendedOpenOceanStep extends OpenOceanStep {
254
+ quoteData?: any
139
255
  execution?: {
140
256
  status: ExecutionStatus
141
257
  process: Process[]
@@ -147,8 +263,9 @@ interface ExtendedOpenOceanStep extends OpenOceanStep {
147
263
 
148
264
  interface ExtendedRoute extends Route {
149
265
  steps: ExtendedOpenOceanStep[]
150
- data: {
151
- prependedOperatingExpenseCost: string
266
+ prependedOperatingExpenseCost?: string
267
+ data?: {
268
+ prependedOperatingExpenseCost?: string
152
269
  }
153
270
  }
154
271
 
@@ -172,16 +289,18 @@ async function executeSolanaSwap(
172
289
  const txData: any = step.transactionRequest?.data || ''
173
290
  const dexId = step.transactionRequest?.type || 0
174
291
  if (step.action.fromChainId === step.action.toChainId) {
175
- if (dexId == 6 || dexId == 7 || dexId == 9) {
292
+ if (dexId === 6 || dexId === 7 || dexId === 9) {
176
293
  transaction = VersionedTransaction.deserialize(hexToUint8Array(txData))
177
294
  } else {
178
295
  transaction = Transaction.from(hexToUint8Array(txData))
179
296
  }
180
297
  } else {
181
- transaction = VersionedTransaction.deserialize(hexToUint8Array(txData.slice(2)))
298
+ transaction = VersionedTransaction.deserialize(
299
+ hexToUint8Array(txData.slice(2))
300
+ )
182
301
 
183
- const { blockhash } = await connection.getLatestBlockhash();
184
- transaction.message.recentBlockhash = blockhash;
302
+ const { blockhash } = await connection.getLatestBlockhash()
303
+ transaction.message.recentBlockhash = blockhash
185
304
  }
186
305
 
187
306
  // Check signTransaction method exists
@@ -254,7 +373,7 @@ async function executeEvmSwap(
254
373
  ): Promise<void> {
255
374
  try {
256
375
  let walletClient = await getWalletClient(options.wagmiConfig)
257
-
376
+
258
377
  // Check if wallet is connected
259
378
  if (!walletClient) {
260
379
  if (options.account?.connector && options.onDisconnect) {
@@ -265,18 +384,18 @@ async function executeEvmSwap(
265
384
  }
266
385
  throw new Error('Please connect wallet first')
267
386
  }
268
-
387
+
269
388
  // Check if current chain matches target chain
270
389
  const currentChainId = walletClient.chain.id
271
390
  const targetChainId = step.action.fromChainId
272
-
391
+
273
392
  if (currentChainId !== targetChainId) {
274
393
  try {
275
394
  // Try to switch to target chain
276
395
  await walletClient.switchChain({ id: targetChainId })
277
-
396
+
278
397
  // Get updated walletClient after chain switch
279
- walletClient = await getWalletClient(options.wagmiConfig) as any
398
+ walletClient = (await getWalletClient(options.wagmiConfig)) as any
280
399
  if (!walletClient || walletClient.chain.id !== targetChainId) {
281
400
  throw new Error('Failed to switch chain')
282
401
  }
@@ -299,19 +418,23 @@ async function executeEvmSwap(
299
418
  throw new Error('Public client not found')
300
419
  }
301
420
 
302
- console.log(
303
- 'Current Chain:',
304
- publicClient.chain?.id,
305
- publicClient.chain?.name
306
- )
307
- console.log('Token Address:', step.action.fromToken.address)
308
- console.log('Token Chain ID:', step.action.fromToken.chainId)
309
- console.log('Owner Address:', walletClient.account.address)
310
- console.log('Spender Address:', step.estimate.approvalAddress)
311
-
421
+ // console.log(
422
+ // 'Current Chain:',
423
+ // publicClient.chain?.id,
424
+ // publicClient.chain?.name
425
+ // )
426
+ // console.log('Token Address:', step.action.fromToken.address)
427
+ // console.log('Token Chain ID:', step.action.fromToken.chainId)
428
+ // console.log('Owner Address:', walletClient.account.address)
429
+ // console.log('Spender Address:', step.estimate.approvalAddress)
312
430
  // Check token approval
313
431
  if (
314
- ['0x0000000000000000000000000000000000000000', '0x0000000000000000000000000000000000001010'].indexOf(step.action.fromToken.address) === -1
432
+ [
433
+ '0x0000000000000000000000000000000000000000',
434
+ '0x0000000000000000000000000000000000001010',
435
+ ].indexOf(step.action.fromToken.address) === -1 &&
436
+ step.estimate.approvalAddress !==
437
+ '0x0000000000000000000000000000000000000000'
315
438
  ) {
316
439
  let allowance = 0n
317
440
  try {
@@ -347,7 +470,11 @@ async function executeEvmSwap(
347
470
 
348
471
  const amount =
349
472
  BigInt(step.action.fromAmount) +
350
- BigInt(route?.data?.prependedOperatingExpenseCost || '0')
473
+ BigInt(
474
+ route?.prependedOperatingExpenseCost ||
475
+ route?.data?.prependedOperatingExpenseCost ||
476
+ '0'
477
+ )
351
478
  if (allowance < BigInt(amount)) {
352
479
  const approvalAmount = options.infiniteApproval
353
480
  ? BigInt(
@@ -382,58 +509,68 @@ async function executeEvmSwap(
382
509
  }
383
510
  }
384
511
 
385
- const { transactionRequest } = step || {}
386
- const txRequest = {
387
- chain: publicClient.chain,
388
- to: transactionRequest?.to as `0x${string}`,
389
- data: (transactionRequest?.data as `0x${string}`) || '0x',
390
- value: BigInt(transactionRequest?.value || '0x0'),
391
- account: walletClient.account.address,
392
- }
512
+ const { transactionRequest, type, quoteData } = step || {}
513
+ let hash: any = ''
514
+ if ((type as any) === 'bridge') {
515
+ const result = await bridgeExecuteSwap({
516
+ quoteData: quoteData,
517
+ walletClient: walletClient,
518
+ })
519
+ hash = result.sourceTxHash
520
+ } else {
521
+ const txRequest = {
522
+ chain: publicClient.chain,
523
+ to: transactionRequest?.to as `0x${string}`,
524
+ data: (transactionRequest?.data as `0x${string}`) || '0x',
525
+ value: BigInt(transactionRequest?.value || '0x0'),
526
+ account: walletClient.account.address,
527
+ }
393
528
 
394
- // 在这里根据useSettingsStore 中的 dynamicSlippage 参数来判断是否调用下面的函数 swap_quote_mev
395
- const { dynamicSlippage } = useSettingsStore.getState()
396
- if (dynamicSlippage) {
397
- try {
398
- // 构建 response 对象
399
- const response = {
400
- inAmount: step.action.fromAmount || '0',
401
- inToken: step.action.fromToken,
402
- data: transactionRequest?.data,
403
- from: walletClient.account.address,
404
- to: transactionRequest?.to,
405
- value: transactionRequest?.value || '0'
406
- };
407
-
408
- // 调用 swap_quote_mev 获取调整后的交易数据
409
- const adjustedResponse = await swapQuoteMEV(response, { publicClient });
410
-
411
- // 如果 swap_quote_mev 返回了修改后的数据,更新交易请求
412
- if (adjustedResponse && adjustedResponse.data !== response.data) {
413
- txRequest.data = adjustedResponse.data as `0x${string}`;
414
- txRequest.value = BigInt(adjustedResponse.value || '0');
415
- console.log('Applied MEV protection with dynamic slippage');
529
+ // Check if dynamicSlippage is enabled in useSettingsStore to determine whether to call swap_quote_mev
530
+ const { dynamicSlippage } = useSettingsStore.getState()
531
+ if (dynamicSlippage) {
532
+ try {
533
+ // Build response object
534
+ const response = {
535
+ inAmount: step.action.fromAmount || '0',
536
+ inToken: step.action.fromToken,
537
+ data: transactionRequest?.data,
538
+ from: walletClient.account.address,
539
+ to: transactionRequest?.to,
540
+ value: transactionRequest?.value || '0',
541
+ }
542
+
543
+ // Call swap_quote_mev to get adjusted transaction data
544
+ const adjustedResponse = await swapQuoteMEV(response, {
545
+ publicClient,
546
+ })
547
+
548
+ // If swap_quote_mev returns modified data, update transaction request
549
+ if (adjustedResponse && adjustedResponse.data !== response.data) {
550
+ txRequest.data = adjustedResponse.data as `0x${string}`
551
+ txRequest.value = BigInt(adjustedResponse.value || '0')
552
+ // Applied MEV protection with dynamic slippage
553
+ }
554
+ } catch (error) {
555
+ console.error('Failed to apply MEV protection:', error)
556
+ // Continue with original transaction request on error
416
557
  }
417
- } catch (error) {
418
- console.error('Failed to apply MEV protection:', error);
419
- // 错误时继续使用原始交易请求
420
558
  }
421
- }
422
559
 
423
- // Estimate gas
424
- const estimatedGas = await publicClient.estimateGas(txRequest)
425
- console.log('estimatedGas', estimatedGas)
560
+ // Estimate gas
561
+ const estimatedGas = await publicClient.estimateGas(txRequest)
426
562
 
427
- // Add estimated gas to transaction request (using 2x the estimated value to ensure transaction success)
428
- const finalTxRequest = {
429
- ...txRequest,
430
- gas: estimatedGas * 2n,
431
- }
563
+ // Add estimated gas to transaction request (using 2x the estimated value to ensure transaction success)
564
+ const finalTxRequest = {
565
+ ...txRequest,
566
+ gas: estimatedGas * 2n,
567
+ }
432
568
 
433
- const hash = await walletClient.sendTransaction({
434
- ...finalTxRequest,
435
- kzg: undefined,
436
- })
569
+ hash = await walletClient.sendTransaction({
570
+ ...finalTxRequest,
571
+ kzg: undefined,
572
+ })
573
+ }
437
574
 
438
575
  process.status = 'PENDING'
439
576
  process.txHash = hash
@@ -476,120 +613,6 @@ async function executeEvmSwap(
476
613
  }
477
614
  }
478
615
 
479
- /**
480
- * 将带精度的金额转换为实际金额
481
- * @param amount 带精度的金额
482
- * @param decimals 精度
483
- * @returns 实际金额
484
- */
485
- function decimals2Amount(amount: string | number, decimals = 18): number {
486
- return Number(amount) / Math.pow(10, decimals);
487
- }
488
-
489
- /**
490
- * 交易响应类型
491
- */
492
- interface SwapResponse {
493
- inAmount?: string;
494
- inToken?: {
495
- decimals?: number;
496
- price?: string | number;
497
- priceUSD?: string | number;
498
- address?: string;
499
- };
500
- data?: string;
501
- from?: string;
502
- to?: string;
503
- value?: string;
504
- minOutAmount?: string;
505
- }
506
-
507
- /**
508
- * 根据动态滑点调整交易参数,提供 MEV 保护
509
- */
510
- async function swapQuoteMEV(
511
- response: SwapResponse,
512
- options?: { publicClient?: any }
513
- ): Promise<SwapResponse> {
514
- try {
515
- const inAmount = response?.inAmount;
516
- const inTokenDecimals = response?.inToken?.decimals || 18;
517
- const inTokenPrice = Number(response?.inToken?.priceUSD || 0);
518
- const amount = decimals2Amount(inAmount, inTokenDecimals) * inTokenPrice;
519
- if (amount < 1) {
520
- return response;
521
- }
522
- const { publicClient } = options;
523
- const OPENOCEAN_CONTRACT = new ethers.Contract(
524
- "0x6352a56caadC4F1E25CD6c75970Fa768A3304e64",
525
- OpenOceanABI
526
- );
527
- if (
528
- ethers.hexlify(ethers.getBytes(response?.data || "0x").slice(0, 4)) !==
529
- OPENOCEAN_CONTRACT.interface.getFunction("swap").selector
530
- ) {
531
- return response;
532
- }
533
- let oldCallData = OPENOCEAN_CONTRACT.interface.decodeFunctionData(
534
- "swap",
535
- response?.data
536
- );
537
- let callData = [...oldCallData];
538
- callData[1] = [...oldCallData[1]];
539
- const minOutAmount = BigInt(callData[1][5] || 0);
540
- const outAmount = BigInt(callData[1][6] || 0);
541
- const slippageAmount = outAmount - minOutAmount;
542
-
543
- let minOutAmounts = await Promise.all(
544
- [1, 2, 3].map(async (i) => {
545
- const mockMinOutAmount = minOutAmount + (slippageAmount / 4n) * BigInt(i);
546
- callData[1][5] = mockMinOutAmount;
547
- const params = {
548
- from: response?.from as `0x${string}`,
549
- to: response?.to as `0x${string}`,
550
- data: OPENOCEAN_CONTRACT.interface.encodeFunctionData(
551
- "swap",
552
- callData
553
- ) as `0x${string}`,
554
- value: BigInt(response?.value || '0'),
555
- };
556
- try {
557
- await publicClient.estimateGas(params);
558
- return mockMinOutAmount;
559
- } catch (error) {
560
- console.error('Failed to estimate gas:', error);
561
- return undefined;
562
- }
563
- })
564
- );
565
- let [min1, min2] = minOutAmounts
566
- .filter((value) => value !== undefined)
567
- .sort((a, b) => (BigInt(b || 0) > BigInt(a || 0) ? 1 : -1))
568
- .slice(0, 2);
569
- min1 = min1 ?? minOutAmount;
570
- min2 = min2 ?? minOutAmount;
571
-
572
- const randomFactor = BigInt(Math.floor(Math.random() * 10000));
573
- const minOutAmountDiff = BigInt(min1 || 0) - BigInt(min2 || 0);
574
- const finalMinOutAmount = BigInt(min2 || 0) +
575
- (minOutAmountDiff * randomFactor / BigInt(10000));
576
-
577
- if (finalMinOutAmount < minOutAmount) {
578
- return response;
579
- }
580
- callData[1][5] = finalMinOutAmount;
581
- const finalCallData = OPENOCEAN_CONTRACT.interface.encodeFunctionData(
582
- "swap",
583
- callData
584
- );
585
- response.minOutAmount = finalMinOutAmount.toString();
586
- response.data = finalCallData;
587
- return response;
588
- } catch (error) {
589
- return response;
590
- }
591
- }
592
-
593
616
  // Execute transaction
594
617
  async function executeSwap(
595
618
  route: ExtendedRoute,