@openocean.finance/widget 1.0.30 → 1.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/config/version.d.ts +1 -1
- package/dist/esm/config/version.js +1 -1
- package/dist/esm/cross/adapters/BaseSwapAdapter.d.ts +2 -2
- package/dist/esm/cross/adapters/BaseSwapAdapter.js +2 -2
- package/dist/esm/cross/adapters/BaseSwapAdapter.js.map +1 -1
- package/dist/esm/cross/adapters/RelayAdapter.js +11 -14
- package/dist/esm/cross/adapters/RelayAdapter.js.map +1 -1
- package/dist/esm/cross/crossChainQuote.d.ts +2 -2
- package/dist/esm/cross/crossChainQuote.js +6 -6
- package/dist/esm/cross/crossChainQuote.js.map +1 -1
- package/dist/esm/cross/factory.js +1 -1
- package/dist/esm/cross/factory.js.map +1 -1
- package/dist/esm/hooks/useRouteExecution.js +2 -0
- package/dist/esm/hooks/useRouteExecution.js.map +1 -1
- package/dist/esm/hooks/useRoutes.js +25 -4
- package/dist/esm/hooks/useRoutes.js.map +1 -1
- package/dist/esm/services/ExecuteRoute.d.ts +1 -0
- package/dist/esm/services/ExecuteRoute.js +65 -51
- package/dist/esm/services/ExecuteRoute.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/config/version.ts +1 -1
- package/src/cross/adapters/BaseSwapAdapter.ts +2 -2
- package/src/cross/adapters/RelayAdapter.ts +13 -19
- package/src/cross/crossChainQuote.ts +8 -9
- package/src/cross/factory.ts +1 -1
- package/src/hooks/useRouteExecution.ts +2 -0
- package/src/hooks/useRoutes.ts +26 -15
- package/src/services/ExecuteRoute.ts +78 -54
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openocean.finance/widget",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.32",
|
|
4
4
|
"description": "Openocean Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/esm/index.js",
|
package/src/config/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const name = '@openocean.finance/widget'
|
|
2
|
-
export const version = '1.0.
|
|
2
|
+
export const version = '1.0.32'
|
|
@@ -31,7 +31,6 @@ import {
|
|
|
31
31
|
CROSS_CHAIN_FEE_RECEIVER,
|
|
32
32
|
CROSS_CHAIN_FEE_RECEIVER_SOLANA,
|
|
33
33
|
MAINNET_NETWORKS,
|
|
34
|
-
type SolanaToken,
|
|
35
34
|
ZERO_ADDRESS,
|
|
36
35
|
} from '../constants/index.js'
|
|
37
36
|
|
|
@@ -93,7 +92,8 @@ export class RelayAdapter extends BaseSwapAdapter {
|
|
|
93
92
|
return 'https://storage.googleapis.com/ks-setting-1d682dca/84e906bb-eaeb-45d3-a64c-2aa9c84eb3ea1747759080942.png'
|
|
94
93
|
}
|
|
95
94
|
getSupportedChains(): Chain[] {
|
|
96
|
-
return [NonEvmChain.Solana, ...MAINNET_NETWORKS]
|
|
95
|
+
// return [NonEvmChain.Solana, ...MAINNET_NETWORKS]
|
|
96
|
+
return [...MAINNET_NETWORKS]
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
getSupportedTokens(_sourceChain: Chain, _destChain: Chain): Currency[] {
|
|
@@ -103,24 +103,15 @@ export class RelayAdapter extends BaseSwapAdapter {
|
|
|
103
103
|
async getQuote(params: QuoteParams): Promise<NormalizedQuote> {
|
|
104
104
|
const evmFromToken = params.fromToken as Currency
|
|
105
105
|
const evmToToken = params.toToken as Currency
|
|
106
|
-
const currency =
|
|
107
|
-
|
|
108
|
-
? (params.fromToken as SolanaToken).id
|
|
109
|
-
: evmFromToken.isNative
|
|
110
|
-
? ZERO_ADDRESS
|
|
111
|
-
: evmFromToken.address
|
|
112
|
-
|
|
113
|
-
const toCurrency =
|
|
114
|
-
params.toChain === 'solana'
|
|
115
|
-
? (params.toToken as SolanaToken).id
|
|
116
|
-
: evmToToken.isNative
|
|
117
|
-
? ZERO_ADDRESS
|
|
118
|
-
: evmToToken.address
|
|
119
|
-
|
|
106
|
+
const currency = evmFromToken.isNative ? ZERO_ADDRESS : evmFromToken.address
|
|
107
|
+
const toCurrency = evmToToken.isNative ? ZERO_ADDRESS : evmToToken.address
|
|
120
108
|
const resp = await getClient().actions.getQuote({
|
|
121
109
|
chainId:
|
|
122
|
-
params.fromChain ===
|
|
123
|
-
|
|
110
|
+
params.fromChain === NonEvmChain.Solana
|
|
111
|
+
? SolanaChainId
|
|
112
|
+
: +params.fromChain,
|
|
113
|
+
toChainId:
|
|
114
|
+
params.toChain === NonEvmChain.Solana ? SolanaChainId : +params.toChain,
|
|
124
115
|
currency,
|
|
125
116
|
toCurrency,
|
|
126
117
|
amount: params.amount,
|
|
@@ -131,7 +122,10 @@ export class RelayAdapter extends BaseSwapAdapter {
|
|
|
131
122
|
options: {
|
|
132
123
|
appFees: [
|
|
133
124
|
{
|
|
134
|
-
recipient:
|
|
125
|
+
recipient:
|
|
126
|
+
params.fromChain === NonEvmChain.Solana
|
|
127
|
+
? CROSS_CHAIN_FEE_RECEIVER_SOLANA
|
|
128
|
+
: CROSS_CHAIN_FEE_RECEIVER,
|
|
135
129
|
fee: params.feeBps.toString(),
|
|
136
130
|
},
|
|
137
131
|
],
|
|
@@ -14,7 +14,7 @@ export async function getCrossChainQuote({
|
|
|
14
14
|
inAmount,
|
|
15
15
|
slippage_tolerance,
|
|
16
16
|
account,
|
|
17
|
-
|
|
17
|
+
recipient,
|
|
18
18
|
tokenInUsd = 0,
|
|
19
19
|
tokenOutUsd = 0,
|
|
20
20
|
feeBps = 10,
|
|
@@ -27,7 +27,7 @@ export async function getCrossChainQuote({
|
|
|
27
27
|
inAmount: string
|
|
28
28
|
slippage_tolerance: string | number
|
|
29
29
|
account: string
|
|
30
|
-
|
|
30
|
+
recipient?: string
|
|
31
31
|
tokenInUsd?: number
|
|
32
32
|
tokenOutUsd?: number
|
|
33
33
|
feeBps?: number
|
|
@@ -57,7 +57,7 @@ export async function getCrossChainQuote({
|
|
|
57
57
|
tokenInUsd,
|
|
58
58
|
tokenOutUsd,
|
|
59
59
|
sender: account,
|
|
60
|
-
recipient:
|
|
60
|
+
recipient: recipient || '',
|
|
61
61
|
publicKey,
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -66,13 +66,12 @@ export async function getCrossChainQuote({
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
// 3. Get all quotes
|
|
69
|
-
const adapters = registry
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
(
|
|
73
|
-
adapter.getSupportedChains().includes(params.fromChain) &&
|
|
74
|
-
adapter.getSupportedChains().includes(params.toChain)
|
|
69
|
+
const adapters = registry.getAllAdapters().filter((adapter) => {
|
|
70
|
+
return (
|
|
71
|
+
adapter.getSupportedChains().includes(params.fromChain) &&
|
|
72
|
+
adapter.getSupportedChains().includes(params.toChain)
|
|
75
73
|
)
|
|
74
|
+
})
|
|
76
75
|
|
|
77
76
|
if (adapters.length === 0) {
|
|
78
77
|
console.warn('No supported adapters found for the specified chains')
|
package/src/cross/factory.ts
CHANGED
|
@@ -101,7 +101,7 @@ export class CrossChainSwapFactory {
|
|
|
101
101
|
// Get all registered adapters
|
|
102
102
|
static getAllAdapters(): SwapProvider[] {
|
|
103
103
|
return [
|
|
104
|
-
|
|
104
|
+
CrossChainSwapFactory.getMayanAdapter(),
|
|
105
105
|
CrossChainSwapFactory.getRelayAdapter(),
|
|
106
106
|
|
|
107
107
|
// CrossChainSwapFactory.getAcrossAdapter(),
|
|
@@ -46,6 +46,7 @@ export const useRouteExecution = ({
|
|
|
46
46
|
const wagmiConfig = useConfig()
|
|
47
47
|
const disconnect = useAccountDisconnect()
|
|
48
48
|
const { openWalletMenu } = useWalletMenu()
|
|
49
|
+
// const { wallet: solanaWallet } = useWallet()
|
|
49
50
|
const resumedAfterMount = useRef(false)
|
|
50
51
|
const emitter = useWidgetEvents()
|
|
51
52
|
const routeExecutionStoreContext = useRouteExecutionStoreContext()
|
|
@@ -149,6 +150,7 @@ export const useRouteExecution = ({
|
|
|
149
150
|
wagmiConfig,
|
|
150
151
|
onDisconnect: disconnect,
|
|
151
152
|
onOpenWalletMenu: openWalletMenu,
|
|
153
|
+
// solanaWallet: solanaWallet?.adapter,
|
|
152
154
|
})
|
|
153
155
|
},
|
|
154
156
|
onMutate: () => {
|
package/src/hooks/useRoutes.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useAccount } from '@openocean.finance/wallet-management'
|
|
2
2
|
import type { Route } from '@openocean.finance/widget-sdk'
|
|
3
|
-
import { OpenOceanErrorCode } from '@openocean.finance/widget-sdk'
|
|
3
|
+
import { ChainType, OpenOceanErrorCode } from '@openocean.finance/widget-sdk'
|
|
4
|
+
import { useWallet } from '@solana/wallet-adapter-react'
|
|
4
5
|
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
|
5
6
|
import { parseUnits } from 'viem'
|
|
6
7
|
import { useConfig } from 'wagmi'
|
|
@@ -32,18 +33,9 @@ interface RoutesProps {
|
|
|
32
33
|
|
|
33
34
|
export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
34
35
|
const wagmiConfig = useConfig()
|
|
36
|
+
const { wallet: solanaWallet } = useWallet()
|
|
35
37
|
|
|
36
|
-
const {
|
|
37
|
-
subvariant,
|
|
38
|
-
sdkConfig,
|
|
39
|
-
contractTool,
|
|
40
|
-
bridges,
|
|
41
|
-
exchanges,
|
|
42
|
-
fee,
|
|
43
|
-
feeConfig,
|
|
44
|
-
useRelayerRoutes,
|
|
45
|
-
referrer,
|
|
46
|
-
} = useWidgetConfig()
|
|
38
|
+
const { subvariant, sdkConfig, fee, feeConfig, referrer } = useWidgetConfig()
|
|
47
39
|
const setExecutableRoute = useSetExecutableRoute()
|
|
48
40
|
const queryClient = useQueryClient()
|
|
49
41
|
const emitter = useWidgetEvents()
|
|
@@ -215,8 +207,22 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
215
207
|
chainId: toChainId,
|
|
216
208
|
}
|
|
217
209
|
|
|
218
|
-
|
|
219
|
-
|
|
210
|
+
// Get appropriate wallet client based on chain type
|
|
211
|
+
let walletClient = undefined
|
|
212
|
+
if (fromChain?.chainType === ChainType.EVM) {
|
|
213
|
+
try {
|
|
214
|
+
walletClient = await getWalletClient(wagmiConfig)
|
|
215
|
+
} catch (error) {
|
|
216
|
+
console.warn(
|
|
217
|
+
'Failed to get wallet client for EVM chain:',
|
|
218
|
+
error
|
|
219
|
+
)
|
|
220
|
+
// Continue without walletClient for non-EVM chains
|
|
221
|
+
}
|
|
222
|
+
} else if (fromChain?.chainType === ChainType.SVM) {
|
|
223
|
+
// For Solana chains, use the Solana wallet adapter
|
|
224
|
+
walletClient = solanaWallet?.adapter
|
|
225
|
+
}
|
|
220
226
|
quoteResult = await getCrossChainQuote({
|
|
221
227
|
feeBps: 10,
|
|
222
228
|
fromMsg,
|
|
@@ -225,6 +231,7 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
225
231
|
slippage_tolerance: formattedSlippage,
|
|
226
232
|
account: account?.address || '',
|
|
227
233
|
walletClient,
|
|
234
|
+
recipient: toAddress || '',
|
|
228
235
|
})
|
|
229
236
|
|
|
230
237
|
// quoteResult = await DebridgeService.swapUThenCross({
|
|
@@ -281,6 +288,10 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
281
288
|
quoteResult.isBridge = false
|
|
282
289
|
}
|
|
283
290
|
}
|
|
291
|
+
if (!quoteResult) {
|
|
292
|
+
return []
|
|
293
|
+
}
|
|
294
|
+
// biome-ignore lint/complexity/useOptionalChain: <explanation>
|
|
284
295
|
const data = (quoteResult && quoteResult.data) || {}
|
|
285
296
|
// minOutAmount calculation is now handled within DebridgeService or OpenOceanService
|
|
286
297
|
const isBridge = quoteResult.isBridge
|
|
@@ -355,7 +366,7 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
355
366
|
fromAmount: fromAmount.toString(),
|
|
356
367
|
toAmount: data?.outAmount || '0',
|
|
357
368
|
toAmountMin,
|
|
358
|
-
approvalAddress: data?.approveContract || '0x0',
|
|
369
|
+
approvalAddress: data?.approveContract || data?.to || '0x0',
|
|
359
370
|
executionDuration:
|
|
360
371
|
data?.executionDuration ||
|
|
361
372
|
Math.floor(Math.random() * 20) + 40,
|
|
@@ -248,6 +248,7 @@ interface ExecuteRouteOptions {
|
|
|
248
248
|
wagmiConfig: any // Use any to avoid deep type instantiation
|
|
249
249
|
onDisconnect?: (account: Account) => Promise<void>
|
|
250
250
|
onOpenWalletMenu?: () => void
|
|
251
|
+
solanaWallet?: any
|
|
251
252
|
}
|
|
252
253
|
|
|
253
254
|
interface ExtendedOpenOceanStep extends OpenOceanStep {
|
|
@@ -274,7 +275,8 @@ async function executeSolanaSwap(
|
|
|
274
275
|
step: ExtendedOpenOceanStep,
|
|
275
276
|
options: ExecuteRouteOptions,
|
|
276
277
|
process: Process,
|
|
277
|
-
route: ExtendedRoute
|
|
278
|
+
route: ExtendedRoute,
|
|
279
|
+
solanaWallet?: any
|
|
278
280
|
): Promise<void> {
|
|
279
281
|
try {
|
|
280
282
|
// Check wallet connection status
|
|
@@ -286,63 +288,78 @@ async function executeSolanaSwap(
|
|
|
286
288
|
const connection = new Connection(
|
|
287
289
|
'https://burned-practical-bird.solana-mainnet.quiknode.pro/33f4786133c252415e194b29ee69ffc7671480ab'
|
|
288
290
|
)
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
291
|
+
const { transactionRequest, type, quoteData } = step || {}
|
|
292
|
+
if ((type as any) === 'bridge') {
|
|
293
|
+
const result = await bridgeExecuteSwap({
|
|
294
|
+
quoteData: quoteData,
|
|
295
|
+
walletClient: solanaWallet,
|
|
296
|
+
})
|
|
297
|
+
const hash = result.sourceTxHash
|
|
298
|
+
process.status = 'PENDING'
|
|
299
|
+
process.txHash = hash
|
|
300
|
+
process.message = 'Transaction pending'
|
|
301
|
+
options.updateRouteHook?.(route)
|
|
297
302
|
} else {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
)
|
|
303
|
+
const txData: any = transactionRequest?.data || ''
|
|
304
|
+
const dexId = transactionRequest?.type || 0
|
|
305
|
+
if (step.action.fromChainId === step.action.toChainId) {
|
|
306
|
+
if (dexId === 6 || dexId === 7 || dexId === 9) {
|
|
307
|
+
transaction = VersionedTransaction.deserialize(
|
|
308
|
+
hexToUint8Array(txData)
|
|
309
|
+
)
|
|
310
|
+
} else {
|
|
311
|
+
transaction = Transaction.from(hexToUint8Array(txData))
|
|
312
|
+
}
|
|
313
|
+
} else {
|
|
314
|
+
transaction = VersionedTransaction.deserialize(
|
|
315
|
+
hexToUint8Array(txData.slice(2))
|
|
316
|
+
)
|
|
301
317
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
318
|
+
const { blockhash } = await connection.getLatestBlockhash()
|
|
319
|
+
transaction.message.recentBlockhash = blockhash
|
|
320
|
+
}
|
|
305
321
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
322
|
+
// Check signTransaction method exists
|
|
323
|
+
const connector = options.account.connector as any
|
|
324
|
+
if (typeof connector.signTransaction !== 'function') {
|
|
325
|
+
throw new Error('Wallet does not support transaction signing')
|
|
326
|
+
}
|
|
311
327
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
328
|
+
// Sign transaction
|
|
329
|
+
const signedTx = await connector.signTransaction(transaction)
|
|
330
|
+
if (!signedTx) {
|
|
331
|
+
throw new Error('Failed to sign transaction')
|
|
332
|
+
}
|
|
317
333
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
334
|
+
// Serialize signed transaction
|
|
335
|
+
const serializedTransaction = signedTx.serialize({
|
|
336
|
+
verifySignatures: false,
|
|
337
|
+
requireAllSignatures: false,
|
|
338
|
+
})
|
|
323
339
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
340
|
+
// Use improved transaction sender
|
|
341
|
+
await sendAndConfirmSolanaTransaction({
|
|
342
|
+
connection,
|
|
343
|
+
serializedTransaction,
|
|
344
|
+
process,
|
|
345
|
+
updateRouteHook: (updatedProcess) => {
|
|
346
|
+
// Update process status
|
|
347
|
+
Object.assign(process, updatedProcess)
|
|
348
|
+
|
|
349
|
+
// Update step execution status
|
|
350
|
+
if (process.status === 'DONE') {
|
|
351
|
+
step.execution!.status = 'DONE'
|
|
352
|
+
} else if (process.status === 'FAILED') {
|
|
353
|
+
step.execution!.status = 'FAILED'
|
|
354
|
+
} else {
|
|
355
|
+
step.execution!.status = 'PENDING'
|
|
356
|
+
}
|
|
341
357
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
358
|
+
// Call original updateRouteHook
|
|
359
|
+
options.updateRouteHook?.(route)
|
|
360
|
+
},
|
|
361
|
+
})
|
|
362
|
+
}
|
|
346
363
|
} catch (error) {
|
|
347
364
|
console.error('Solana swap execution failed:', error)
|
|
348
365
|
process.status = 'FAILED'
|
|
@@ -616,7 +633,8 @@ async function executeEvmSwap(
|
|
|
616
633
|
// Execute transaction
|
|
617
634
|
async function executeSwap(
|
|
618
635
|
route: ExtendedRoute,
|
|
619
|
-
options: ExecuteRouteOptions
|
|
636
|
+
options: ExecuteRouteOptions,
|
|
637
|
+
solanaWallet?: any
|
|
620
638
|
): Promise<Route> {
|
|
621
639
|
const updatedRoute = { ...route }
|
|
622
640
|
|
|
@@ -655,7 +673,13 @@ async function executeSwap(
|
|
|
655
673
|
// Execute different transaction logic based on chain type
|
|
656
674
|
const currentStep = route.steps[0]
|
|
657
675
|
if (currentStep.action?.fromChainId === 1151111081099710) {
|
|
658
|
-
await executeSolanaSwap(
|
|
676
|
+
await executeSolanaSwap(
|
|
677
|
+
currentStep,
|
|
678
|
+
options,
|
|
679
|
+
process,
|
|
680
|
+
updatedRoute,
|
|
681
|
+
solanaWallet
|
|
682
|
+
)
|
|
659
683
|
} else {
|
|
660
684
|
await executeEvmSwap(currentStep, options, process, updatedRoute)
|
|
661
685
|
}
|
|
@@ -688,5 +712,5 @@ export async function executeRoute(
|
|
|
688
712
|
throw new Error('Wallet not connected')
|
|
689
713
|
}
|
|
690
714
|
|
|
691
|
-
return executeSwap(route as ExtendedRoute, options)
|
|
715
|
+
return executeSwap(route as ExtendedRoute, options, options.solanaWallet)
|
|
692
716
|
}
|