@openocean.finance/widget 1.0.32 → 1.0.34
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/RelayAdapter.js +2 -2
- package/dist/esm/cross/adapters/RelayAdapter.js.map +1 -1
- package/dist/esm/hooks/useRouteExecution.js +3 -2
- package/dist/esm/hooks/useRouteExecution.js.map +1 -1
- package/dist/esm/services/ExecuteRoute.js +47 -9
- package/dist/esm/services/ExecuteRoute.js.map +1 -1
- package/dist/esm/services/SendAndConfirmSolanaTransaction.d.ts +2 -2
- package/dist/esm/services/SendAndConfirmSolanaTransaction.js +6 -6
- package/dist/esm/services/SendAndConfirmSolanaTransaction.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/src/config/version.ts +1 -1
- package/src/cross/adapters/RelayAdapter.ts +2 -2
- package/src/hooks/useRouteExecution.ts +3 -3
- package/src/services/ExecuteRoute.ts +59 -18
- package/src/services/SendAndConfirmSolanaTransaction.ts +76 -67
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openocean.finance/widget",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.34",
|
|
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",
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"@solana/wallet-adapter-base": "^0.9.24",
|
|
59
59
|
"@solana/web3.js": "^1.98.0",
|
|
60
60
|
"@tanstack/react-virtual": "^3.13.4",
|
|
61
|
+
"@reservoir0x/relay-solana-wallet-adapter": "^2.0.5",
|
|
61
62
|
"ethers": "^6.13.5",
|
|
62
63
|
"i18next": "^24.2.3",
|
|
63
64
|
"microdiff": "^1.5.0",
|
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.34'
|
|
@@ -92,8 +92,8 @@ export class RelayAdapter extends BaseSwapAdapter {
|
|
|
92
92
|
return 'https://storage.googleapis.com/ks-setting-1d682dca/84e906bb-eaeb-45d3-a64c-2aa9c84eb3ea1747759080942.png'
|
|
93
93
|
}
|
|
94
94
|
getSupportedChains(): Chain[] {
|
|
95
|
-
|
|
96
|
-
return [...MAINNET_NETWORKS]
|
|
95
|
+
return [NonEvmChain.Solana, ...MAINNET_NETWORKS]
|
|
96
|
+
// return [...MAINNET_NETWORKS]
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
getSupportedTokens(_sourceChain: Chain, _destChain: Chain): Currency[] {
|
|
@@ -10,7 +10,7 @@ import type {
|
|
|
10
10
|
import { updateRouteExecution } from '@openocean.finance/widget-sdk'
|
|
11
11
|
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
|
12
12
|
import { useCallback, useEffect, useRef } from 'react'
|
|
13
|
-
import { useConfig } from 'wagmi'
|
|
13
|
+
import { useConfig, useWalletClient } from 'wagmi'
|
|
14
14
|
import { shallow } from 'zustand/shallow'
|
|
15
15
|
import { executeRoute } from '../services/ExecuteRoute.js'
|
|
16
16
|
import {
|
|
@@ -26,7 +26,6 @@ import {
|
|
|
26
26
|
import { WidgetEvent } from '../types/events.js'
|
|
27
27
|
import { useAvailableChains } from './useAvailableChains.js'
|
|
28
28
|
import { useWidgetEvents } from './useWidgetEvents.js'
|
|
29
|
-
|
|
30
29
|
interface RouteExecutionProps {
|
|
31
30
|
routeId: string
|
|
32
31
|
executeInBackground?: boolean
|
|
@@ -46,6 +45,7 @@ export const useRouteExecution = ({
|
|
|
46
45
|
const wagmiConfig = useConfig()
|
|
47
46
|
const disconnect = useAccountDisconnect()
|
|
48
47
|
const { openWalletMenu } = useWalletMenu()
|
|
48
|
+
const solanaWallet = useWalletClient()
|
|
49
49
|
// const { wallet: solanaWallet } = useWallet()
|
|
50
50
|
const resumedAfterMount = useRef(false)
|
|
51
51
|
const emitter = useWidgetEvents()
|
|
@@ -150,7 +150,7 @@ export const useRouteExecution = ({
|
|
|
150
150
|
wagmiConfig,
|
|
151
151
|
onDisconnect: disconnect,
|
|
152
152
|
onOpenWalletMenu: openWalletMenu,
|
|
153
|
-
|
|
153
|
+
solanaWallet: solanaWallet,
|
|
154
154
|
})
|
|
155
155
|
},
|
|
156
156
|
onMutate: () => {
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
Process,
|
|
6
6
|
Route,
|
|
7
7
|
} from '@openocean.finance/widget-sdk'
|
|
8
|
+
import { adaptSolanaWallet } from '@reservoir0x/relay-solana-wallet-adapter'
|
|
8
9
|
import { Connection, Transaction, VersionedTransaction } from '@solana/web3.js'
|
|
9
10
|
import { ethers } from 'ethers'
|
|
10
11
|
import { getPublicClient, getWalletClient } from 'wagmi/actions'
|
|
@@ -275,8 +276,7 @@ async function executeSolanaSwap(
|
|
|
275
276
|
step: ExtendedOpenOceanStep,
|
|
276
277
|
options: ExecuteRouteOptions,
|
|
277
278
|
process: Process,
|
|
278
|
-
route: ExtendedRoute
|
|
279
|
-
solanaWallet?: any
|
|
279
|
+
route: ExtendedRoute
|
|
280
280
|
): Promise<void> {
|
|
281
281
|
try {
|
|
282
282
|
// Check wallet connection status
|
|
@@ -288,17 +288,66 @@ async function executeSolanaSwap(
|
|
|
288
288
|
const connection = new Connection(
|
|
289
289
|
'https://burned-practical-bird.solana-mainnet.quiknode.pro/33f4786133c252415e194b29ee69ffc7671480ab'
|
|
290
290
|
)
|
|
291
|
+
|
|
291
292
|
const { transactionRequest, type, quoteData } = step || {}
|
|
292
293
|
if ((type as any) === 'bridge') {
|
|
293
|
-
const
|
|
294
|
+
const adaptedWallet: any = adaptSolanaWallet(
|
|
295
|
+
options.account.address?.toString() ||
|
|
296
|
+
'1nc1nerator11111111111111111111111111111111',
|
|
297
|
+
792703809, //chain id that Relay uses to identify solana
|
|
298
|
+
connection,
|
|
299
|
+
async (transaction) => {
|
|
300
|
+
try {
|
|
301
|
+
// Ensure transaction is properly formatted
|
|
302
|
+
if (
|
|
303
|
+
transaction instanceof VersionedTransaction ||
|
|
304
|
+
transaction instanceof Transaction
|
|
305
|
+
) {
|
|
306
|
+
const connector = options.account.connector as any
|
|
307
|
+
if (typeof connector.signTransaction !== 'function') {
|
|
308
|
+
throw new Error('Wallet does not support transaction signing')
|
|
309
|
+
}
|
|
310
|
+
// Sign transaction
|
|
311
|
+
const signature = await connector.signTransaction(transaction)
|
|
312
|
+
const serializedTransaction = signature.serialize({
|
|
313
|
+
verifySignatures: false,
|
|
314
|
+
requireAllSignatures: false,
|
|
315
|
+
})
|
|
316
|
+
const txid = await connection.sendRawTransaction(
|
|
317
|
+
serializedTransaction,
|
|
318
|
+
{
|
|
319
|
+
skipPreflight: true,
|
|
320
|
+
}
|
|
321
|
+
)
|
|
322
|
+
return { signature: txid }
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
throw new Error('Invalid transaction type')
|
|
326
|
+
} catch (error) {
|
|
327
|
+
console.error('Transaction sending failed:', error)
|
|
328
|
+
throw error
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
)
|
|
332
|
+
const signedTx = await bridgeExecuteSwap({
|
|
294
333
|
quoteData: quoteData,
|
|
295
|
-
walletClient:
|
|
334
|
+
walletClient: adaptedWallet,
|
|
296
335
|
})
|
|
297
|
-
|
|
298
|
-
|
|
336
|
+
if (!signedTx) {
|
|
337
|
+
throw new Error('Failed to sign transaction')
|
|
338
|
+
}
|
|
339
|
+
const hash = signedTx.sourceTxHash
|
|
340
|
+
|
|
341
|
+
process.status = 'DONE'
|
|
342
|
+
process.doneAt = Date.now()
|
|
299
343
|
process.txHash = hash
|
|
300
|
-
process.message = 'Transaction
|
|
344
|
+
process.message = 'Transaction confirmed'
|
|
301
345
|
options.updateRouteHook?.(route)
|
|
346
|
+
|
|
347
|
+
// process.status = 'PENDING'
|
|
348
|
+
// process.txHash = hash
|
|
349
|
+
// process.message = 'Transaction pending'
|
|
350
|
+
// options.updateRouteHook?.(route)
|
|
302
351
|
} else {
|
|
303
352
|
const txData: any = transactionRequest?.data || ''
|
|
304
353
|
const dexId = transactionRequest?.type || 0
|
|
@@ -633,8 +682,7 @@ async function executeEvmSwap(
|
|
|
633
682
|
// Execute transaction
|
|
634
683
|
async function executeSwap(
|
|
635
684
|
route: ExtendedRoute,
|
|
636
|
-
options: ExecuteRouteOptions
|
|
637
|
-
solanaWallet?: any
|
|
685
|
+
options: ExecuteRouteOptions
|
|
638
686
|
): Promise<Route> {
|
|
639
687
|
const updatedRoute = { ...route }
|
|
640
688
|
|
|
@@ -673,13 +721,7 @@ async function executeSwap(
|
|
|
673
721
|
// Execute different transaction logic based on chain type
|
|
674
722
|
const currentStep = route.steps[0]
|
|
675
723
|
if (currentStep.action?.fromChainId === 1151111081099710) {
|
|
676
|
-
await executeSolanaSwap(
|
|
677
|
-
currentStep,
|
|
678
|
-
options,
|
|
679
|
-
process,
|
|
680
|
-
updatedRoute,
|
|
681
|
-
solanaWallet
|
|
682
|
-
)
|
|
724
|
+
await executeSolanaSwap(currentStep, options, process, updatedRoute)
|
|
683
725
|
} else {
|
|
684
726
|
await executeEvmSwap(currentStep, options, process, updatedRoute)
|
|
685
727
|
}
|
|
@@ -711,6 +753,5 @@ export async function executeRoute(
|
|
|
711
753
|
if (!options.account.isConnected) {
|
|
712
754
|
throw new Error('Wallet not connected')
|
|
713
755
|
}
|
|
714
|
-
|
|
715
|
-
return executeSwap(route as ExtendedRoute, options, options.solanaWallet)
|
|
756
|
+
return executeSwap(route as ExtendedRoute, options)
|
|
716
757
|
}
|
|
@@ -1,37 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Solana Transaction Sending Service
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* This module handles sending and confirming transactions on Solana blockchain
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import type {
|
|
8
|
+
BlockhashWithExpiryBlockHeight,
|
|
9
|
+
Connection,
|
|
10
|
+
} from '@solana/web3.js'
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
* Delay execution helper
|
|
11
14
|
* @param ms Delay time in milliseconds
|
|
12
15
|
*/
|
|
13
16
|
const delay = (ms: number): Promise<void> =>
|
|
14
|
-
new Promise((resolve) => setTimeout(resolve, ms))
|
|
17
|
+
new Promise((resolve) => setTimeout(resolve, ms))
|
|
15
18
|
|
|
16
19
|
/**
|
|
17
20
|
* Transaction sending and confirmation parameters interface
|
|
18
21
|
*/
|
|
19
22
|
interface SolanaTransactionParams {
|
|
20
23
|
/** Solana RPC connection instance */
|
|
21
|
-
connection: Connection
|
|
24
|
+
connection: Connection
|
|
22
25
|
/** Serialized transaction data */
|
|
23
|
-
serializedTransaction: Buffer
|
|
26
|
+
serializedTransaction: Buffer
|
|
24
27
|
/** Blockhash with expiry block height */
|
|
25
|
-
blockhashWithExpiryBlockHeight?: BlockhashWithExpiryBlockHeight
|
|
28
|
+
blockhashWithExpiryBlockHeight?: BlockhashWithExpiryBlockHeight
|
|
26
29
|
/** Transaction process object */
|
|
27
|
-
process?: any
|
|
30
|
+
process?: any
|
|
28
31
|
/** Route update callback function */
|
|
29
|
-
updateRouteHook?: (route: any) => void
|
|
32
|
+
updateRouteHook?: (route: any) => void
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
/**
|
|
33
36
|
* Send raw transaction to Solana network
|
|
34
|
-
*
|
|
37
|
+
*
|
|
35
38
|
* @param connection Solana RPC connection instance
|
|
36
39
|
* @param serializedTransaction Serialized transaction data
|
|
37
40
|
* @param process Transaction process object
|
|
@@ -39,44 +42,40 @@ interface SolanaTransactionParams {
|
|
|
39
42
|
* @returns Transaction hash
|
|
40
43
|
*/
|
|
41
44
|
async function sendSolanaTransaction(
|
|
42
|
-
connection: Connection,
|
|
45
|
+
connection: Connection,
|
|
43
46
|
serializedTransaction: Buffer,
|
|
44
47
|
process: any,
|
|
45
48
|
updateRouteHook?: (route: any) => void
|
|
46
49
|
): Promise<string> {
|
|
47
50
|
try {
|
|
48
51
|
// Send transaction to network
|
|
49
|
-
const txid = await connection.sendRawTransaction(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
skipPreflight: true,
|
|
53
|
-
}
|
|
54
|
-
);
|
|
55
|
-
console.log('Transaction sent:', txid);
|
|
56
|
-
|
|
52
|
+
const txid = await connection.sendRawTransaction(serializedTransaction, {
|
|
53
|
+
skipPreflight: true,
|
|
54
|
+
})
|
|
57
55
|
// Update transaction status to pending
|
|
58
56
|
if (process && updateRouteHook) {
|
|
59
|
-
process.status = 'PENDING'
|
|
60
|
-
process.txHash = txid
|
|
61
|
-
process.message = 'Transaction pending'
|
|
62
|
-
updateRouteHook(process.route)
|
|
57
|
+
process.status = 'PENDING'
|
|
58
|
+
process.txHash = txid
|
|
59
|
+
process.message = 'Transaction pending'
|
|
60
|
+
updateRouteHook(process.route)
|
|
63
61
|
}
|
|
64
62
|
|
|
65
|
-
return txid
|
|
63
|
+
return txid
|
|
66
64
|
} catch (error) {
|
|
67
|
-
console.error('Failed to send transaction:', error)
|
|
65
|
+
console.error('Failed to send transaction:', error)
|
|
68
66
|
if (process && updateRouteHook) {
|
|
69
|
-
process.status = 'FAILED'
|
|
70
|
-
process.message =
|
|
71
|
-
|
|
67
|
+
process.status = 'FAILED'
|
|
68
|
+
process.message =
|
|
69
|
+
error instanceof Error ? error.message : 'Failed to send transaction'
|
|
70
|
+
updateRouteHook(process.route)
|
|
72
71
|
}
|
|
73
|
-
throw error
|
|
72
|
+
throw error
|
|
74
73
|
}
|
|
75
74
|
}
|
|
76
75
|
|
|
77
76
|
/**
|
|
78
77
|
* Confirm Solana transaction status
|
|
79
|
-
*
|
|
78
|
+
*
|
|
80
79
|
* @param connection Solana RPC connection instance
|
|
81
80
|
* @param txid Transaction hash
|
|
82
81
|
* @param process Transaction process object
|
|
@@ -89,59 +88,59 @@ async function confirmSolanaTransaction(
|
|
|
89
88
|
txid: string,
|
|
90
89
|
process: any,
|
|
91
90
|
updateRouteHook?: (route: any) => void,
|
|
92
|
-
maxRetries
|
|
91
|
+
maxRetries = 30
|
|
93
92
|
): Promise<boolean> {
|
|
94
|
-
let retries = 0
|
|
95
|
-
|
|
93
|
+
let retries = 0
|
|
94
|
+
|
|
96
95
|
while (retries < maxRetries) {
|
|
97
96
|
try {
|
|
98
97
|
// Get latest blockhash
|
|
99
|
-
const latestBlockhash = await connection.getLatestBlockhash()
|
|
100
|
-
|
|
98
|
+
const latestBlockhash = await connection.getLatestBlockhash()
|
|
99
|
+
|
|
101
100
|
// Confirm transaction status
|
|
102
101
|
const confirmation = await connection.confirmTransaction({
|
|
103
102
|
signature: txid,
|
|
104
103
|
blockhash: latestBlockhash.blockhash,
|
|
105
|
-
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
|
|
106
|
-
})
|
|
104
|
+
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
|
|
105
|
+
})
|
|
107
106
|
|
|
108
107
|
// Check if transaction failed
|
|
109
108
|
if (confirmation.value.err) {
|
|
110
109
|
if (process && updateRouteHook) {
|
|
111
|
-
process.status = 'FAILED'
|
|
112
|
-
process.message = 'Transaction failed on chain'
|
|
113
|
-
updateRouteHook(process.route)
|
|
110
|
+
process.status = 'FAILED'
|
|
111
|
+
process.message = 'Transaction failed on chain'
|
|
112
|
+
updateRouteHook(process.route)
|
|
114
113
|
}
|
|
115
|
-
return false
|
|
114
|
+
return false
|
|
116
115
|
}
|
|
117
116
|
|
|
118
117
|
// Transaction confirmed successfully
|
|
119
118
|
if (process && updateRouteHook) {
|
|
120
|
-
process.status = 'DONE'
|
|
121
|
-
process.doneAt = Date.now()
|
|
122
|
-
process.message = 'Transaction confirmed'
|
|
123
|
-
updateRouteHook(process.route)
|
|
119
|
+
process.status = 'DONE'
|
|
120
|
+
process.doneAt = Date.now()
|
|
121
|
+
process.message = 'Transaction confirmed'
|
|
122
|
+
updateRouteHook(process.route)
|
|
124
123
|
}
|
|
125
|
-
return true
|
|
124
|
+
return true
|
|
126
125
|
} catch (error) {
|
|
127
|
-
console.warn('Confirmation attempt failed:', error)
|
|
128
|
-
await delay(2000)
|
|
129
|
-
retries
|
|
126
|
+
console.warn('Confirmation attempt failed:', error)
|
|
127
|
+
await delay(2000) // Wait 2 seconds before retrying
|
|
128
|
+
retries++
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
131
|
|
|
133
132
|
// Exceeded maximum retry attempts
|
|
134
133
|
if (process && updateRouteHook) {
|
|
135
|
-
process.status = 'FAILED'
|
|
136
|
-
process.message = 'Transaction confirmation timeout'
|
|
137
|
-
updateRouteHook(process.route)
|
|
134
|
+
process.status = 'FAILED'
|
|
135
|
+
process.message = 'Transaction confirmation timeout'
|
|
136
|
+
updateRouteHook(process.route)
|
|
138
137
|
}
|
|
139
|
-
throw new Error('Transaction confirmation timeout')
|
|
138
|
+
throw new Error('Transaction confirmation timeout')
|
|
140
139
|
}
|
|
141
140
|
|
|
142
141
|
/**
|
|
143
142
|
* Send and wait for Solana transaction confirmation
|
|
144
|
-
*
|
|
143
|
+
*
|
|
145
144
|
* @param params Transaction parameters
|
|
146
145
|
* @returns Transaction response and hash
|
|
147
146
|
*/
|
|
@@ -149,32 +148,42 @@ export async function sendAndConfirmSolanaTransaction({
|
|
|
149
148
|
connection,
|
|
150
149
|
serializedTransaction,
|
|
151
150
|
process,
|
|
152
|
-
updateRouteHook
|
|
151
|
+
updateRouteHook,
|
|
153
152
|
}: SolanaTransactionParams): Promise<any> {
|
|
154
153
|
try {
|
|
155
154
|
// Send transaction and get transaction hash
|
|
156
|
-
const txid = await sendSolanaTransaction(
|
|
157
|
-
|
|
155
|
+
const txid = await sendSolanaTransaction(
|
|
156
|
+
connection,
|
|
157
|
+
serializedTransaction,
|
|
158
|
+
process,
|
|
159
|
+
updateRouteHook
|
|
160
|
+
)
|
|
161
|
+
|
|
158
162
|
// Wait for transaction confirmation
|
|
159
|
-
const success = await confirmSolanaTransaction(
|
|
160
|
-
|
|
163
|
+
const success = await confirmSolanaTransaction(
|
|
164
|
+
connection,
|
|
165
|
+
txid,
|
|
166
|
+
process,
|
|
167
|
+
updateRouteHook
|
|
168
|
+
)
|
|
169
|
+
|
|
161
170
|
if (!success) {
|
|
162
|
-
throw new Error('Transaction failed during confirmation')
|
|
171
|
+
throw new Error('Transaction failed during confirmation')
|
|
163
172
|
}
|
|
164
173
|
|
|
165
174
|
// Get transaction details
|
|
166
175
|
const response = await connection.getTransaction(txid, {
|
|
167
|
-
commitment:
|
|
168
|
-
maxSupportedTransactionVersion: 0
|
|
169
|
-
})
|
|
176
|
+
commitment: 'confirmed',
|
|
177
|
+
maxSupportedTransactionVersion: 0,
|
|
178
|
+
})
|
|
170
179
|
|
|
171
180
|
if (!response) {
|
|
172
|
-
throw new Error('Failed to fetch transaction details')
|
|
181
|
+
throw new Error('Failed to fetch transaction details')
|
|
173
182
|
}
|
|
174
183
|
|
|
175
|
-
return { response, txid }
|
|
184
|
+
return { response, txid }
|
|
176
185
|
} catch (error) {
|
|
177
|
-
console.error('Transaction failed:', error)
|
|
178
|
-
throw error
|
|
186
|
+
console.error('Transaction failed:', error)
|
|
187
|
+
throw error
|
|
179
188
|
}
|
|
180
|
-
}
|
|
189
|
+
}
|