@openocean.finance/widget 1.0.28 → 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.
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.js +46 -39
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.js.map +1 -1
- package/dist/esm/components/Messages/WarningMessages.js +2 -2
- package/dist/esm/components/Messages/WarningMessages.js.map +1 -1
- package/dist/esm/components/Step/Step.js +37 -29
- package/dist/esm/components/Step/Step.js.map +1 -1
- package/dist/esm/components/TransactionDetails.js +2 -5
- package/dist/esm/components/TransactionDetails.js.map +1 -1
- package/dist/esm/config/version.d.ts +1 -1
- package/dist/esm/config/version.js +1 -1
- package/dist/esm/cross/adapters/AcrossAdapter.d.ts +15 -0
- package/dist/esm/cross/adapters/AcrossAdapter.js +166 -0
- package/dist/esm/cross/adapters/AcrossAdapter.js.map +1 -0
- package/dist/esm/cross/adapters/BaseSwapAdapter.d.ts +107 -0
- package/dist/esm/cross/adapters/BaseSwapAdapter.js +44 -0
- package/dist/esm/cross/adapters/BaseSwapAdapter.js.map +1 -0
- package/dist/esm/cross/adapters/DebridgeAdapter.d.ts +20 -0
- package/dist/esm/cross/adapters/DebridgeAdapter.js +264 -0
- package/dist/esm/cross/adapters/DebridgeAdapter.js.map +1 -0
- package/dist/esm/cross/adapters/LifiAdapter.d.ts +19 -0
- package/dist/esm/cross/adapters/LifiAdapter.js +169 -0
- package/dist/esm/cross/adapters/LifiAdapter.js.map +1 -0
- package/dist/esm/cross/adapters/MayanAdapter.d.ts +14 -0
- package/dist/esm/cross/adapters/MayanAdapter.js +119 -0
- package/dist/esm/cross/adapters/MayanAdapter.js.map +1 -0
- package/dist/esm/cross/adapters/NearIntentsAdapter.d.ts +21 -0
- package/dist/esm/cross/adapters/NearIntentsAdapter.js +425 -0
- package/dist/esm/cross/adapters/NearIntentsAdapter.js.map +1 -0
- package/dist/esm/cross/adapters/OptimexAdapter.d.ts +19 -0
- package/dist/esm/cross/adapters/OptimexAdapter.js +216 -0
- package/dist/esm/cross/adapters/OptimexAdapter.js.map +1 -0
- package/dist/esm/cross/adapters/OrbiterAdapter.d.ts +20 -0
- package/dist/esm/cross/adapters/OrbiterAdapter.js +213 -0
- package/dist/esm/cross/adapters/OrbiterAdapter.js.map +1 -0
- package/dist/esm/cross/adapters/RelayAdapter.d.ts +14 -0
- package/dist/esm/cross/adapters/RelayAdapter.js +171 -0
- package/dist/esm/cross/adapters/RelayAdapter.js.map +1 -0
- package/dist/esm/cross/adapters/SymbiosisAdapter.d.ts +14 -0
- package/dist/esm/cross/adapters/SymbiosisAdapter.js +120 -0
- package/dist/esm/cross/adapters/SymbiosisAdapter.js.map +1 -0
- package/dist/esm/cross/adapters/XYFinanceAdapter.d.ts +14 -0
- package/dist/esm/cross/adapters/XYFinanceAdapter.js +177 -0
- package/dist/esm/cross/adapters/XYFinanceAdapter.js.map +1 -0
- package/dist/esm/cross/adapters/index.d.ts +2 -0
- package/dist/esm/cross/adapters/index.js +10 -0
- package/dist/esm/cross/adapters/index.js.map +1 -0
- package/dist/esm/cross/constants/index.d.ts +202 -0
- package/dist/esm/cross/constants/index.js +183 -0
- package/dist/esm/cross/constants/index.js.map +1 -0
- package/dist/esm/cross/crossChainQuote.d.ts +25 -0
- package/dist/esm/cross/crossChainQuote.js +127 -0
- package/dist/esm/cross/crossChainQuote.js.map +1 -0
- package/dist/esm/cross/factory.d.ts +9 -0
- package/dist/esm/cross/factory.js +125 -0
- package/dist/esm/cross/factory.js.map +1 -0
- package/dist/esm/cross/registry.d.ts +12 -0
- package/dist/esm/cross/registry.js +52 -0
- package/dist/esm/cross/registry.js.map +1 -0
- package/dist/esm/hooks/useChain.d.ts +1 -1
- package/dist/esm/hooks/useGasRefuel.d.ts +1 -1
- package/dist/esm/hooks/useGasSufficiencyBridge.js +1 -2
- package/dist/esm/hooks/useGasSufficiencyBridge.js.map +1 -1
- package/dist/esm/hooks/useRouteExecution.js +2 -1
- package/dist/esm/hooks/useRouteExecution.js.map +1 -1
- package/dist/esm/hooks/useRoutes.js +50 -32
- package/dist/esm/hooks/useRoutes.js.map +1 -1
- package/dist/esm/hooks/useSettingMonitor.js +1 -0
- package/dist/esm/hooks/useSettingMonitor.js.map +1 -1
- package/dist/esm/hooks/useTokenAddressBalance.d.ts +1 -1
- package/dist/esm/hooks/useTokenPrice.js +4 -2
- package/dist/esm/hooks/useTokenPrice.js.map +1 -1
- package/dist/esm/hooks/useTokens.d.ts +1 -1
- package/dist/esm/services/ExecuteRoute.js +142 -124
- package/dist/esm/services/ExecuteRoute.js.map +1 -1
- package/dist/esm/stores/form/useFieldController.d.ts +1 -1
- package/dist/esm/stores/routes/createRouteExecutionStore.js +6 -3
- package/dist/esm/stores/routes/createRouteExecutionStore.js.map +1 -1
- package/dist/esm/stores/routes/useSetExecutableRoute.d.ts +1 -1
- package/dist/esm/types/widget.d.ts +3 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +14 -4
- package/src/components/AmountInput/AmountInputEndAdornment.tsx +46 -46
- package/src/components/Messages/WarningMessages.tsx +7 -2
- package/src/components/Step/Step.tsx +37 -31
- package/src/components/TransactionDetails.tsx +10 -11
- package/src/config/version.ts +1 -1
- package/src/cross/adapters/AcrossAdapter.ts +193 -0
- package/src/cross/adapters/BaseSwapAdapter.ts +173 -0
- package/src/cross/adapters/DebridgeAdapter.ts +375 -0
- package/src/cross/adapters/LifiAdapter.ts +213 -0
- package/src/cross/adapters/MayanAdapter.ts +179 -0
- package/src/cross/adapters/NearIntentsAdapter.ts +539 -0
- package/src/cross/adapters/OptimexAdapter.ts +273 -0
- package/src/cross/adapters/OrbiterAdapter.ts +270 -0
- package/src/cross/adapters/RelayAdapter.ts +248 -0
- package/src/cross/adapters/SymbiosisAdapter.ts +144 -0
- package/src/cross/adapters/XYFinanceAdapter.ts +213 -0
- package/src/cross/adapters/index.ts +9 -0
- package/src/cross/constants/index.ts +223 -0
- package/src/cross/crossChainQuote.ts +181 -0
- package/src/cross/factory.ts +145 -0
- package/src/cross/registry.ts +65 -0
- package/src/hooks/useGasSufficiencyBridge.ts +1 -3
- package/src/hooks/useRouteExecution.ts +2 -1
- package/src/hooks/useRoutes.ts +64 -43
- package/src/hooks/useSettingMonitor.ts +1 -1
- package/src/hooks/useTokenPrice.ts +5 -3
- package/src/services/ExecuteRoute.ts +184 -171
- package/src/stores/routes/createRouteExecutionStore.ts +13 -4
- package/src/types/widget.ts +3 -0
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { ChainId } from '@openocean.finance/widget-sdk'
|
|
2
|
+
|
|
3
|
+
export const CROSS_CHAIN_FEE_RECEIVER =
|
|
4
|
+
'0x922164BBBd36Acf9E854AcBbF32faCC949fCAEef'
|
|
5
|
+
export const CROSS_CHAIN_FEE_RECEIVER_SOLANA =
|
|
6
|
+
'yEVG5DpokLuVRAqoWeKJANBY2wynzgTSXUbGz7aDKBq'
|
|
7
|
+
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
|
|
8
|
+
export const BTC_DEFAULT_RECEIVER = ''
|
|
9
|
+
export const SOLANA_NATIVE = '11111111111111111111111111111111'
|
|
10
|
+
export const ETHER_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE'
|
|
11
|
+
export const TOKEN_API_URL = 'https://token-api.kyberengineering.io/api'
|
|
12
|
+
export const NativeCurrencies = {
|
|
13
|
+
[ChainId.ETH]: {
|
|
14
|
+
name: 'Ether',
|
|
15
|
+
symbol: 'ETH',
|
|
16
|
+
decimals: 18,
|
|
17
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
18
|
+
wrapped: {
|
|
19
|
+
name: 'Wrapped Ether',
|
|
20
|
+
symbol: 'WETH',
|
|
21
|
+
decimals: 18,
|
|
22
|
+
address: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
[ChainId.BSC]: {
|
|
26
|
+
name: 'Binance Coin',
|
|
27
|
+
symbol: 'BNB',
|
|
28
|
+
decimals: 18,
|
|
29
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
30
|
+
wrapped: {
|
|
31
|
+
name: 'Wrapped BNB',
|
|
32
|
+
symbol: 'WBNB',
|
|
33
|
+
decimals: 18,
|
|
34
|
+
address: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
[ChainId.AVA]: {
|
|
38
|
+
name: 'Avalanche',
|
|
39
|
+
symbol: 'AVAX',
|
|
40
|
+
decimals: 18,
|
|
41
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
42
|
+
wrapped: {
|
|
43
|
+
name: 'Wrapped AVAX',
|
|
44
|
+
symbol: 'WAVAX',
|
|
45
|
+
decimals: 18,
|
|
46
|
+
address: '0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
[ChainId.POL]: {
|
|
50
|
+
name: 'Polygon',
|
|
51
|
+
symbol: 'MATIC',
|
|
52
|
+
decimals: 18,
|
|
53
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
54
|
+
wrapped: {
|
|
55
|
+
name: 'Wrapped MATIC',
|
|
56
|
+
symbol: 'WMATIC',
|
|
57
|
+
decimals: 18,
|
|
58
|
+
address: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
[ChainId.ARB]: {
|
|
62
|
+
name: 'ETH',
|
|
63
|
+
symbol: 'ETH',
|
|
64
|
+
decimals: 18,
|
|
65
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
66
|
+
wrapped: {
|
|
67
|
+
name: 'Wrapped ETH',
|
|
68
|
+
symbol: 'WEHT',
|
|
69
|
+
decimals: 18,
|
|
70
|
+
address: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
[ChainId.OPT]: {
|
|
74
|
+
name: 'Optimism',
|
|
75
|
+
symbol: 'ETH',
|
|
76
|
+
decimals: 18,
|
|
77
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
78
|
+
wrapped: {
|
|
79
|
+
name: 'Wrapped ETH',
|
|
80
|
+
symbol: 'WETH',
|
|
81
|
+
decimals: 18,
|
|
82
|
+
address: '0x4200000000000000000000000000000000000006',
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
[ChainId.FTM]: {
|
|
86
|
+
name: 'Fantom',
|
|
87
|
+
symbol: 'FTM',
|
|
88
|
+
decimals: 18,
|
|
89
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
90
|
+
wrapped: {
|
|
91
|
+
name: 'Wrapped FTM',
|
|
92
|
+
symbol: 'WFTM',
|
|
93
|
+
decimals: 18,
|
|
94
|
+
address: '0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
[ChainId.BAS]: {
|
|
98
|
+
name: 'Base',
|
|
99
|
+
symbol: 'ETH',
|
|
100
|
+
decimals: 18,
|
|
101
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
102
|
+
wrapped: {
|
|
103
|
+
name: 'Wrapped ETH',
|
|
104
|
+
symbol: 'WEHT',
|
|
105
|
+
decimals: 18,
|
|
106
|
+
address: '0x4200000000000000000000000000000000000006',
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
[ChainId.SCL]: {
|
|
110
|
+
name: 'Scroll',
|
|
111
|
+
symbol: 'ETH',
|
|
112
|
+
decimals: 18,
|
|
113
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
114
|
+
wrapped: {
|
|
115
|
+
name: 'Wrapped ETH',
|
|
116
|
+
symbol: 'WEHT',
|
|
117
|
+
decimals: 18,
|
|
118
|
+
address: '0x5300000000000000000000000000000000000004',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
[ChainId.BLS]: {
|
|
122
|
+
name: 'Blast',
|
|
123
|
+
symbol: 'ETH',
|
|
124
|
+
decimals: 18,
|
|
125
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
126
|
+
wrapped: {
|
|
127
|
+
name: 'Wrapped ETH',
|
|
128
|
+
symbol: 'WEHT',
|
|
129
|
+
decimals: 18,
|
|
130
|
+
address: '0x4300000000000000000000000000000000000004',
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
[ChainId.MNT]: {
|
|
134
|
+
name: 'Mantle',
|
|
135
|
+
symbol: 'ETH',
|
|
136
|
+
decimals: 18,
|
|
137
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
138
|
+
wrapped: {
|
|
139
|
+
name: 'Wrapped MNT',
|
|
140
|
+
symbol: 'WMNT',
|
|
141
|
+
decimals: 18,
|
|
142
|
+
address: '0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8',
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
[ChainId.SON]: {
|
|
146
|
+
name: 'Son',
|
|
147
|
+
symbol: 'S',
|
|
148
|
+
decimals: 18,
|
|
149
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
150
|
+
wrapped: {
|
|
151
|
+
name: 'Wrapped S',
|
|
152
|
+
symbol: 'WS',
|
|
153
|
+
decimals: 18,
|
|
154
|
+
address: '0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38',
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
[ChainId.UNI]: {
|
|
158
|
+
name: 'UniChain',
|
|
159
|
+
symbol: 'ETH',
|
|
160
|
+
decimals: 18,
|
|
161
|
+
address: '0x0000000000000000000000000000000000000000',
|
|
162
|
+
wrapped: {
|
|
163
|
+
name: 'Wrapped ETH',
|
|
164
|
+
symbol: 'WEHT',
|
|
165
|
+
decimals: 18,
|
|
166
|
+
address: '0x4200000000000000000000000000000000000006',
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
}
|
|
170
|
+
export const MAINNET_NETWORKS = [
|
|
171
|
+
ChainId.ETH,
|
|
172
|
+
ChainId.BSC,
|
|
173
|
+
ChainId.AVA,
|
|
174
|
+
ChainId.BAS,
|
|
175
|
+
ChainId.POL,
|
|
176
|
+
ChainId.ARB,
|
|
177
|
+
ChainId.OPT,
|
|
178
|
+
// ChainId.FTM,
|
|
179
|
+
// ChainId.MAM,
|
|
180
|
+
ChainId.MNT,
|
|
181
|
+
ChainId.SON,
|
|
182
|
+
ChainId.UNI,
|
|
183
|
+
ChainId.BLS,
|
|
184
|
+
ChainId.SCL,
|
|
185
|
+
] as const
|
|
186
|
+
|
|
187
|
+
export interface Currency {
|
|
188
|
+
id: string
|
|
189
|
+
name: string
|
|
190
|
+
symbol: string
|
|
191
|
+
address: string
|
|
192
|
+
icon: string
|
|
193
|
+
logo: string
|
|
194
|
+
decimals: number
|
|
195
|
+
isNative: boolean
|
|
196
|
+
wrapped: {
|
|
197
|
+
name: string
|
|
198
|
+
symbol: string
|
|
199
|
+
decimals: number
|
|
200
|
+
address: string
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export interface NearToken {
|
|
205
|
+
assetId: string
|
|
206
|
+
decimals: number
|
|
207
|
+
blockchain: string
|
|
208
|
+
symbol: string
|
|
209
|
+
price: number
|
|
210
|
+
priceUpdatedAt: number
|
|
211
|
+
contractAddress: string
|
|
212
|
+
logo: string
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export interface SolanaToken {
|
|
216
|
+
id: string
|
|
217
|
+
name: string
|
|
218
|
+
symbol: string
|
|
219
|
+
icon: string
|
|
220
|
+
logo: string
|
|
221
|
+
decimals: number
|
|
222
|
+
tokenProgram: string
|
|
223
|
+
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import type { WalletClient } from 'viem'
|
|
2
|
+
import type { QuoteParams } from './adapters/index.js'
|
|
3
|
+
import { CrossChainSwapFactory } from './factory.js'
|
|
4
|
+
import { CrossChainSwapAdapterRegistry, type Quote } from './registry.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Get cross-chain aggregated quotes (supports multiple adapter comparison)
|
|
8
|
+
* @param params - Cross-chain quote parameters
|
|
9
|
+
* @returns Best quote result, compatible with useRoutes.ts requirements
|
|
10
|
+
*/
|
|
11
|
+
export async function getCrossChainQuote({
|
|
12
|
+
fromMsg,
|
|
13
|
+
toMsg,
|
|
14
|
+
inAmount,
|
|
15
|
+
slippage_tolerance,
|
|
16
|
+
account,
|
|
17
|
+
receiver,
|
|
18
|
+
tokenInUsd = 0,
|
|
19
|
+
tokenOutUsd = 0,
|
|
20
|
+
feeBps = 10,
|
|
21
|
+
walletClient,
|
|
22
|
+
publicKey,
|
|
23
|
+
nearTokens = [],
|
|
24
|
+
}: {
|
|
25
|
+
fromMsg: any
|
|
26
|
+
toMsg: any
|
|
27
|
+
inAmount: string
|
|
28
|
+
slippage_tolerance: string | number
|
|
29
|
+
account: string
|
|
30
|
+
receiver?: string
|
|
31
|
+
tokenInUsd?: number
|
|
32
|
+
tokenOutUsd?: number
|
|
33
|
+
feeBps?: number
|
|
34
|
+
walletClient?: any
|
|
35
|
+
publicKey?: string
|
|
36
|
+
nearTokens?: any[]
|
|
37
|
+
}): Promise<any | null> {
|
|
38
|
+
try {
|
|
39
|
+
// 1. Register all Adapters
|
|
40
|
+
const registry = new CrossChainSwapAdapterRegistry()
|
|
41
|
+
CrossChainSwapFactory.getAllAdapters().forEach((adapter) => {
|
|
42
|
+
registry.registerAdapter(adapter)
|
|
43
|
+
})
|
|
44
|
+
// 2. Construct QuoteParams
|
|
45
|
+
const params: QuoteParams = {
|
|
46
|
+
feeBps,
|
|
47
|
+
fromChain: fromMsg.chainId,
|
|
48
|
+
toChain: toMsg.chainId,
|
|
49
|
+
fromToken: fromMsg,
|
|
50
|
+
toToken: toMsg,
|
|
51
|
+
amount: inAmount,
|
|
52
|
+
slippage:
|
|
53
|
+
typeof slippage_tolerance === 'string'
|
|
54
|
+
? Number.parseFloat(slippage_tolerance)
|
|
55
|
+
: slippage_tolerance,
|
|
56
|
+
walletClient,
|
|
57
|
+
tokenInUsd,
|
|
58
|
+
tokenOutUsd,
|
|
59
|
+
sender: account,
|
|
60
|
+
recipient: receiver || account,
|
|
61
|
+
publicKey,
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (fromMsg.chainId === 'near' || toMsg.chainId === 'near') {
|
|
65
|
+
;(params as any).nearTokens = nearTokens
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 3. Get all quotes
|
|
69
|
+
const adapters = registry
|
|
70
|
+
.getAllAdapters()
|
|
71
|
+
.filter(
|
|
72
|
+
(adapter) =>
|
|
73
|
+
adapter.getSupportedChains().includes(params.fromChain) &&
|
|
74
|
+
adapter.getSupportedChains().includes(params.toChain)
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
if (adapters.length === 0) {
|
|
78
|
+
console.warn('No supported adapters found for the specified chains')
|
|
79
|
+
return null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const quoteResults: Quote[] = []
|
|
83
|
+
|
|
84
|
+
// Get quotes from all adapters in parallel
|
|
85
|
+
const quotePromises = adapters.map(async (adapter) => {
|
|
86
|
+
try {
|
|
87
|
+
const quote = await adapter.getQuote(params)
|
|
88
|
+
if (quote) {
|
|
89
|
+
quoteResults.push({ adapter, quote })
|
|
90
|
+
}
|
|
91
|
+
} catch (error) {
|
|
92
|
+
// Ignore individual adapter errors, continue getting quotes from other adapters
|
|
93
|
+
console.warn(`Failed to get quote from ${adapter.getName()}:`, error)
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
await Promise.all(quotePromises)
|
|
98
|
+
|
|
99
|
+
if (quoteResults.length === 0) {
|
|
100
|
+
console.warn('No valid quotes found from any adapter')
|
|
101
|
+
return null
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// 4. Select best quote (highest outputAmount)
|
|
105
|
+
quoteResults.sort((a, b) =>
|
|
106
|
+
a.quote.outputAmount < b.quote.outputAmount ? 1 : -1
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
const best = quoteResults[0]
|
|
110
|
+
|
|
111
|
+
// 5. Construct return structure compatible with useRoutes.ts
|
|
112
|
+
return {
|
|
113
|
+
data: {
|
|
114
|
+
minOutAmount: best.quote.outputAmount || '0',
|
|
115
|
+
outAmount: best.quote.outputAmount || '0',
|
|
116
|
+
fromTokenUSD: best.quote.inputUsd?.toString() || '0',
|
|
117
|
+
toTokenUSD: best.quote.outputUsd?.toString() || '0',
|
|
118
|
+
quoteAdapterName: best.adapter.getName(),
|
|
119
|
+
quoteAdapterKey: best.adapter.getName().toLowerCase(),
|
|
120
|
+
chainId: fromMsg.chainId,
|
|
121
|
+
from: account,
|
|
122
|
+
|
|
123
|
+
to: best.quote.contractAddress || '0x0',
|
|
124
|
+
value: best.quote.rawQuote.tx?.value || '0x0',
|
|
125
|
+
data: best.quote.rawQuote.tx?.data || '0x',
|
|
126
|
+
// gasLimit: best.quote.rawQuote.tx?.gasLimit || '0',
|
|
127
|
+
// gas: best.quote.rawQuote.tx?.gas || '0',
|
|
128
|
+
// nonce: best.quote.rawQuote.tx?.nonce || '0',
|
|
129
|
+
approveContract: best.quote.contractAddress || '0x0',
|
|
130
|
+
executionDuration: best.quote.timeEstimate || 300,
|
|
131
|
+
// Fee information
|
|
132
|
+
feeCosts: [
|
|
133
|
+
{
|
|
134
|
+
name: `${best.adapter.getName()} Fee`,
|
|
135
|
+
description: 'Protocol fee',
|
|
136
|
+
token: fromMsg,
|
|
137
|
+
amount: '0',
|
|
138
|
+
amountUSD: best.quote.protocolFee,
|
|
139
|
+
percentage: '0',
|
|
140
|
+
included: false,
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
// Original quote data
|
|
144
|
+
quoteRawData: best.quote,
|
|
145
|
+
},
|
|
146
|
+
}
|
|
147
|
+
} catch (error) {
|
|
148
|
+
console.error('Error getting cross-chain quote:', error)
|
|
149
|
+
return null
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export const bridgeExecuteSwap = async ({
|
|
154
|
+
quoteData,
|
|
155
|
+
walletClient,
|
|
156
|
+
}: {
|
|
157
|
+
quoteData: any
|
|
158
|
+
walletClient: WalletClient
|
|
159
|
+
}) => {
|
|
160
|
+
const adapterName = quoteData.quoteAdapterKey
|
|
161
|
+
const adapter = CrossChainSwapFactory.getAdapterByName(adapterName)
|
|
162
|
+
const result = await adapter.executeSwap(
|
|
163
|
+
{
|
|
164
|
+
quote: quoteData.quoteRawData,
|
|
165
|
+
},
|
|
166
|
+
walletClient
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
return result
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Login URL mapping for each adapter
|
|
173
|
+
export const ADAPTER_LOGIN_URLS: Record<string, string> = {
|
|
174
|
+
debridge: 'https://app.debridge.finance/',
|
|
175
|
+
across: 'https://across.to/',
|
|
176
|
+
lifi: 'https://jumper.exchange/',
|
|
177
|
+
mayan: 'https://swap.mayan.finance/',
|
|
178
|
+
relay: 'https://app.relay.link/',
|
|
179
|
+
xyfinance: 'https://xy.finance/',
|
|
180
|
+
kyberswap: 'https://kyberswap.com/',
|
|
181
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// import { NearIntentsAdapter } from './adapters/NearIntentsAdapter.js'
|
|
2
|
+
// import { OptimexAdapter } from './adapters/OptimexAdapter.js'
|
|
3
|
+
// import { OrbiterAdapter } from './adapters/OrbiterAdapter.js'
|
|
4
|
+
import {
|
|
5
|
+
// AcrossAdapter,
|
|
6
|
+
// DeBridgeAdapter,
|
|
7
|
+
// LifiAdapter,
|
|
8
|
+
MayanAdapter,
|
|
9
|
+
RelayAdapter,
|
|
10
|
+
// SwapProvider,
|
|
11
|
+
// SymbiosisAdapter,
|
|
12
|
+
// XYFinanceAdapter,
|
|
13
|
+
} from './adapters/index.js'
|
|
14
|
+
|
|
15
|
+
// Factory for creating swap provider instances
|
|
16
|
+
export class CrossChainSwapFactory {
|
|
17
|
+
// Singleton instances (lazy loaded)
|
|
18
|
+
// private static acrossInstance: AcrossAdapter
|
|
19
|
+
private static relayInstance: RelayAdapter
|
|
20
|
+
// private static xyFinanceInstance: XYFinanceAdapter
|
|
21
|
+
// private static nearIntentsInstance: NearIntentsAdapter
|
|
22
|
+
private static mayanInstance: MayanAdapter
|
|
23
|
+
// private static symbiosisInstance: SymbiosisAdapter
|
|
24
|
+
// private static debridgeInstance: DeBridgeAdapter
|
|
25
|
+
// private static lifiInstance: LifiAdapter
|
|
26
|
+
// private static optimexInstance: OptimexAdapter
|
|
27
|
+
// private static orbiterInstance: OrbiterAdapter
|
|
28
|
+
|
|
29
|
+
// // Get or create Across adapter
|
|
30
|
+
// static getAcrossAdapter(): AcrossAdapter {
|
|
31
|
+
// if (!CrossChainSwapFactory.acrossInstance) {
|
|
32
|
+
// CrossChainSwapFactory.acrossInstance = new AcrossAdapter()
|
|
33
|
+
// }
|
|
34
|
+
// return CrossChainSwapFactory.acrossInstance
|
|
35
|
+
// }
|
|
36
|
+
|
|
37
|
+
// // Get or create Relay adapter
|
|
38
|
+
static getRelayAdapter(): RelayAdapter {
|
|
39
|
+
if (!CrossChainSwapFactory.relayInstance) {
|
|
40
|
+
CrossChainSwapFactory.relayInstance = new RelayAdapter()
|
|
41
|
+
}
|
|
42
|
+
return CrossChainSwapFactory.relayInstance
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// static getXyFinanceAdapter(): XYFinanceAdapter {
|
|
46
|
+
// if (!CrossChainSwapFactory.xyFinanceInstance) {
|
|
47
|
+
// CrossChainSwapFactory.xyFinanceInstance = new XYFinanceAdapter()
|
|
48
|
+
// }
|
|
49
|
+
// return CrossChainSwapFactory.xyFinanceInstance
|
|
50
|
+
// }
|
|
51
|
+
|
|
52
|
+
// static getNearIntentsAdapter(): NearIntentsAdapter {
|
|
53
|
+
// if (!CrossChainSwapFactory.nearIntentsInstance) {
|
|
54
|
+
// CrossChainSwapFactory.nearIntentsInstance = new NearIntentsAdapter()
|
|
55
|
+
// }
|
|
56
|
+
// return CrossChainSwapFactory.nearIntentsInstance
|
|
57
|
+
// }
|
|
58
|
+
|
|
59
|
+
static getMayanAdapter(): MayanAdapter {
|
|
60
|
+
if (!CrossChainSwapFactory.mayanInstance) {
|
|
61
|
+
CrossChainSwapFactory.mayanInstance = new MayanAdapter()
|
|
62
|
+
}
|
|
63
|
+
return CrossChainSwapFactory.mayanInstance
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// static getSymbiosisAdapter(): SymbiosisAdapter {
|
|
67
|
+
// if (!CrossChainSwapFactory.symbiosisInstance) {
|
|
68
|
+
// CrossChainSwapFactory.symbiosisInstance = new SymbiosisAdapter()
|
|
69
|
+
// }
|
|
70
|
+
// return CrossChainSwapFactory.symbiosisInstance
|
|
71
|
+
// }
|
|
72
|
+
|
|
73
|
+
// static getDebridgeInstance(): DeBridgeAdapter {
|
|
74
|
+
// if (!CrossChainSwapFactory.debridgeInstance) {
|
|
75
|
+
// CrossChainSwapFactory.debridgeInstance = new DeBridgeAdapter()
|
|
76
|
+
// }
|
|
77
|
+
// return CrossChainSwapFactory.debridgeInstance
|
|
78
|
+
// }
|
|
79
|
+
|
|
80
|
+
// static getLifiInstance(): LifiAdapter {
|
|
81
|
+
// if (!CrossChainSwapFactory.lifiInstance) {
|
|
82
|
+
// CrossChainSwapFactory.lifiInstance = new LifiAdapter()
|
|
83
|
+
// }
|
|
84
|
+
// return CrossChainSwapFactory.lifiInstance
|
|
85
|
+
// }
|
|
86
|
+
|
|
87
|
+
// static getOptimexAdapter(): OptimexAdapter {
|
|
88
|
+
// if (!CrossChainSwapFactory.optimexInstance) {
|
|
89
|
+
// CrossChainSwapFactory.optimexInstance = new OptimexAdapter()
|
|
90
|
+
// }
|
|
91
|
+
// return CrossChainSwapFactory.optimexInstance
|
|
92
|
+
// }
|
|
93
|
+
|
|
94
|
+
// static getOrbiterAdapter(): OrbiterAdapter {
|
|
95
|
+
// if (!CrossChainSwapFactory.orbiterInstance) {
|
|
96
|
+
// CrossChainSwapFactory.orbiterInstance = new OrbiterAdapter()
|
|
97
|
+
// }
|
|
98
|
+
// return CrossChainSwapFactory.orbiterInstance
|
|
99
|
+
// }
|
|
100
|
+
|
|
101
|
+
// Get all registered adapters
|
|
102
|
+
static getAllAdapters(): SwapProvider[] {
|
|
103
|
+
return [
|
|
104
|
+
// CrossChainSwapFactory.getMayanAdapter(),
|
|
105
|
+
CrossChainSwapFactory.getRelayAdapter(),
|
|
106
|
+
|
|
107
|
+
// CrossChainSwapFactory.getAcrossAdapter(),
|
|
108
|
+
// CrossChainSwapFactory.getXyFinanceAdapter(),
|
|
109
|
+
// CrossChainSwapFactory.getNearIntentsAdapter(),
|
|
110
|
+
// CrossChainSwapFactory.getSymbiosisAdapter(),
|
|
111
|
+
// CrossChainSwapFactory.getDebridgeInstance(),
|
|
112
|
+
// CrossChainSwapFactory.getLifiInstance(),
|
|
113
|
+
// CrossChainSwapFactory.getOptimexAdapter(),
|
|
114
|
+
// CrossChainSwapFactory.getOrbiterAdapter(),
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Get adapter by name
|
|
119
|
+
static getAdapterByName(name: string): SwapProvider | undefined {
|
|
120
|
+
switch (name.toLowerCase()) {
|
|
121
|
+
// case 'across':
|
|
122
|
+
// return CrossChainSwapFactory.getAcrossAdapter()
|
|
123
|
+
case 'relay':
|
|
124
|
+
return CrossChainSwapFactory.getRelayAdapter()
|
|
125
|
+
// case 'xyfinance':
|
|
126
|
+
// return CrossChainSwapFactory.getXyFinanceAdapter()
|
|
127
|
+
// case 'near intents':
|
|
128
|
+
// return CrossChainSwapFactory.getNearIntentsAdapter()
|
|
129
|
+
case 'mayan':
|
|
130
|
+
return CrossChainSwapFactory.getMayanAdapter()
|
|
131
|
+
// case 'symbiosis':
|
|
132
|
+
// return CrossChainSwapFactory.getSymbiosisAdapter()
|
|
133
|
+
// case 'debridge':
|
|
134
|
+
// return CrossChainSwapFactory.getDebridgeInstance()
|
|
135
|
+
// case 'lifi':
|
|
136
|
+
// return CrossChainSwapFactory.getLifiInstance()
|
|
137
|
+
// case 'optimex':
|
|
138
|
+
// return CrossChainSwapFactory.getOptimexAdapter()
|
|
139
|
+
// case 'orbiter':
|
|
140
|
+
// return CrossChainSwapFactory.getOrbiterAdapter()
|
|
141
|
+
default:
|
|
142
|
+
return undefined
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// import { isEvmChain } from 'utils'
|
|
2
|
+
import type {
|
|
3
|
+
// NearQuoteParams,
|
|
4
|
+
NormalizedQuote, // QuoteParams,
|
|
5
|
+
SwapProvider,
|
|
6
|
+
} from './adapters/BaseSwapAdapter.js'
|
|
7
|
+
|
|
8
|
+
export interface Quote {
|
|
9
|
+
adapter: SwapProvider
|
|
10
|
+
quote: NormalizedQuote
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class CrossChainSwapAdapterRegistry {
|
|
14
|
+
private adapters: Map<string, SwapProvider> = new Map()
|
|
15
|
+
|
|
16
|
+
registerAdapter(adapter: SwapProvider): void {
|
|
17
|
+
this.adapters.set(adapter.getName().toLowerCase(), adapter)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
getAdapter(name: string): SwapProvider | undefined {
|
|
21
|
+
return this.adapters.get(name.toLowerCase())
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
getAllAdapters(): SwapProvider[] {
|
|
25
|
+
return Array.from(this.adapters.values())
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// get quotes from all adapters and sort them by output amount
|
|
29
|
+
// async getQuotes(params: QuoteParams | NearQuoteParams): Promise<Quote[]> {
|
|
30
|
+
// const quotes: { adapter: SwapProvider; quote: NormalizedQuote }[] = []
|
|
31
|
+
//
|
|
32
|
+
// const adapters =
|
|
33
|
+
// params.fromChain === params.toChain && isEvmChain(params.fromChain)
|
|
34
|
+
// ? ([this.getAdapter('KyberSwap')] as SwapProvider[])
|
|
35
|
+
// : this.getAllAdapters().filter(
|
|
36
|
+
// adapter =>
|
|
37
|
+
// adapter.getSupportedChains().includes(params.fromChain) &&
|
|
38
|
+
// adapter.getSupportedChains().includes(params.toChain),
|
|
39
|
+
// )
|
|
40
|
+
//
|
|
41
|
+
// console.log(
|
|
42
|
+
// 'Available adapters',
|
|
43
|
+
// params,
|
|
44
|
+
// adapters.map(ad => ad.getName()),
|
|
45
|
+
// )
|
|
46
|
+
// // Get quotes from all compatible adapters
|
|
47
|
+
// const quotePromises = adapters.map(async adapter => {
|
|
48
|
+
// try {
|
|
49
|
+
// const quote = await adapter.getQuote(params)
|
|
50
|
+
// quotes.push({ adapter, quote })
|
|
51
|
+
// } catch (err) {
|
|
52
|
+
// console.error(`Failed to get quote from ${adapter.getName()}:`, err)
|
|
53
|
+
// }
|
|
54
|
+
// })
|
|
55
|
+
//
|
|
56
|
+
// await Promise.all(quotePromises)
|
|
57
|
+
//
|
|
58
|
+
// if (quotes.length === 0) {
|
|
59
|
+
// throw new Error('No valid quotes found for the requested swap')
|
|
60
|
+
// }
|
|
61
|
+
//
|
|
62
|
+
// quotes.sort((a, b) => (a.quote.outputAmount < b.quote.outputAmount ? 1 : -1))
|
|
63
|
+
// return quotes
|
|
64
|
+
// }
|
|
65
|
+
}
|
|
@@ -67,9 +67,7 @@ export const useGasSufficiencyBridge = (route?: RouteExtended) => {
|
|
|
67
67
|
} else {
|
|
68
68
|
currentTokenBalance = 0n
|
|
69
69
|
}
|
|
70
|
-
const insufficientFunds =
|
|
71
|
-
BigInt(parsedFromAmount) > currentTokenBalance &&
|
|
72
|
-
BigInt(parsedFromAmount) < token.amount
|
|
70
|
+
const insufficientFunds = BigInt(parsedFromAmount) > currentTokenBalance
|
|
73
71
|
return insufficientFunds
|
|
74
72
|
}
|
|
75
73
|
return false
|
|
@@ -67,7 +67,8 @@ export const useRouteExecution = ({
|
|
|
67
67
|
if (!routeExecution) {
|
|
68
68
|
return
|
|
69
69
|
}
|
|
70
|
-
const
|
|
70
|
+
const safeObj = JSON.parse(JSON.stringify(updatedRoute))
|
|
71
|
+
const clonedUpdatedRoute = structuredClone(safeObj)
|
|
71
72
|
updateRoute(clonedUpdatedRoute)
|
|
72
73
|
const process = getUpdatedProcess(routeExecution.route, clonedUpdatedRoute)
|
|
73
74
|
if (process) {
|