@xswap-link/sdk 0.9.6 → 0.9.8
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/CHANGELOG.md +12 -0
- package/README.md +0 -18
- package/dist/index.d.mts +13 -8
- package/dist/index.d.ts +13 -8
- package/dist/index.global.js +63 -64
- package/dist/index.js +9 -10
- package/dist/index.mjs +9 -10
- package/localTheme.ts +3 -0
- package/package.json +1 -1
- package/src/assets/icons/ChainlinkIcon.tsx +21 -0
- package/src/assets/icons/index.ts +1 -1
- package/src/components/PoweredBy/index.tsx +3 -18
- package/src/components/Swap/SwapView/SwapPanel/ChainPanel/ChainPicker/index.tsx +13 -97
- package/src/components/Swap/SwapView/SwapPanel/ChainPanel/index.tsx +3 -82
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/TokenItem/index.tsx +8 -11
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/index.tsx +0 -1
- package/src/components/TxConfigForm/index.tsx +10 -1
- package/src/components/TxWidgetWC/index.tsx +10 -1
- package/src/components/TxWidgetWCWrapped/index.tsx +2 -0
- package/src/context/SwapProvider.tsx +454 -300
- package/src/models/TokenData.ts +2 -0
- package/src/models/index.ts +0 -1
- package/src/models/payloads/ModalIntegrationPayload.ts +4 -0
- package/src/models/payloads/WidgetIntegrationPayload.ts +3 -0
- package/src/services/api.ts +8 -4
- package/src/utils/index.ts +30 -0
- package/src/utils/validation.ts +19 -25
- package/tailwind.config.js +2 -0
- package/test/context/SwapProvider.test.tsx +220 -4
- package/test/fixtures/supportedChains.mock.ts +7180 -22795
- package/src/assets/icons/ChainlinkCCIPIcon.tsx +0 -23
- package/src/models/XSwapConfig.ts +0 -4
- package/xswap.config.ts +0 -20
package/src/models/TokenData.ts
CHANGED
package/src/models/index.ts
CHANGED
|
@@ -29,6 +29,7 @@ export type ModalIntegrationThemeStyles = {
|
|
|
29
29
|
warningLight?: string;
|
|
30
30
|
errorDark?: string;
|
|
31
31
|
errorLight?: string;
|
|
32
|
+
chainlinkLogo?: string;
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
export type ModalIntegrationStyles = Pick<
|
|
@@ -63,4 +64,7 @@ export type ModalIntegrationPayload = {
|
|
|
63
64
|
onSrcChainChange?: (chain: string | undefined) => void;
|
|
64
65
|
onConnectWallet?: () => void;
|
|
65
66
|
bridge?: boolean;
|
|
67
|
+
override?: {
|
|
68
|
+
apiUrl?: string;
|
|
69
|
+
};
|
|
66
70
|
};
|
package/src/services/api.ts
CHANGED
|
@@ -13,13 +13,18 @@ import {
|
|
|
13
13
|
TransactionHistory,
|
|
14
14
|
TransactionStatus,
|
|
15
15
|
} from "@src/models";
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
let XSWAP_API_URL = "https://xswap.link/api";
|
|
18
|
+
|
|
19
|
+
export const setApiUrl = (url: string) => {
|
|
20
|
+
XSWAP_API_URL = url;
|
|
21
|
+
};
|
|
17
22
|
|
|
18
23
|
async function _sendRequest<T>(
|
|
19
24
|
urlPath: string,
|
|
20
25
|
options?: RequestInit,
|
|
21
26
|
): Promise<T> {
|
|
22
|
-
const response = await fetch(`${
|
|
27
|
+
const response = await fetch(`${XSWAP_API_URL}${urlPath}`, {
|
|
23
28
|
method: "GET",
|
|
24
29
|
headers: {
|
|
25
30
|
"Content-Type": "application/json",
|
|
@@ -59,8 +64,7 @@ export async function getRoute(
|
|
|
59
64
|
* @param ecosystem optional
|
|
60
65
|
*/
|
|
61
66
|
export async function getChains(ecosystem?: Ecosystem): Promise<Chain[]> {
|
|
62
|
-
return _sendRequest<Chain[]>(`/chains?data=${JSON.stringify({ ecosystem })}
|
|
63
|
-
`);
|
|
67
|
+
return _sendRequest<Chain[]>(`/chains?data=${JSON.stringify({ ecosystem })}`);
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
/**
|
package/src/utils/index.ts
CHANGED
|
@@ -3,7 +3,9 @@ export * from "./numbers";
|
|
|
3
3
|
export * from "./parseWeb3Error";
|
|
4
4
|
export * from "./strings";
|
|
5
5
|
|
|
6
|
+
import { Chain } from "@src/models";
|
|
6
7
|
import { format } from "date-fns";
|
|
8
|
+
import { ethers } from "ethers";
|
|
7
9
|
|
|
8
10
|
// eslint-disable-next-line
|
|
9
11
|
export const replaceNull = (values: any[], newValue: any) => {
|
|
@@ -58,3 +60,31 @@ export const getDate = (blockTimestamp: number) => {
|
|
|
58
60
|
};
|
|
59
61
|
|
|
60
62
|
export const isServer = typeof window === "undefined";
|
|
63
|
+
|
|
64
|
+
// Helper function to validate and resolve token addresses
|
|
65
|
+
export const resolveTokenAddress = (
|
|
66
|
+
tokenAddressOrId: string | undefined,
|
|
67
|
+
chainId: string | undefined,
|
|
68
|
+
chains: Chain[],
|
|
69
|
+
): string | undefined => {
|
|
70
|
+
if (!tokenAddressOrId || ethers.utils.isAddress(tokenAddressOrId)) {
|
|
71
|
+
return tokenAddressOrId;
|
|
72
|
+
}
|
|
73
|
+
// try to find the token by the tokenId
|
|
74
|
+
return chains
|
|
75
|
+
.find((chain) => chain.chainId === chainId)
|
|
76
|
+
?.tokens.find((token) => token.tokenId === tokenAddressOrId)
|
|
77
|
+
?.address?.toLowerCase();
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export const sortChains = (chains: Chain[], disabledChainIds: string[]) =>
|
|
81
|
+
[...chains]
|
|
82
|
+
|
|
83
|
+
.map((chain) => ({
|
|
84
|
+
...chain,
|
|
85
|
+
disabled: disabledChainIds.includes(chain.chainId),
|
|
86
|
+
}))
|
|
87
|
+
.sort((a, b) => {
|
|
88
|
+
if (a.disabled === b.disabled) return 0;
|
|
89
|
+
return a.disabled ? 1 : -1;
|
|
90
|
+
});
|
package/src/utils/validation.ts
CHANGED
|
@@ -121,7 +121,7 @@ const isSwapTargetChainValid = ({
|
|
|
121
121
|
|
|
122
122
|
return (
|
|
123
123
|
targetChain.swapSupported &&
|
|
124
|
-
|
|
124
|
+
sourceChain.supportedDstForSwap?.includes(targetChain.chainId)
|
|
125
125
|
);
|
|
126
126
|
};
|
|
127
127
|
|
|
@@ -138,9 +138,16 @@ const isBridgeTargetValid = ({
|
|
|
138
138
|
sourceToken: Token | undefined;
|
|
139
139
|
}) => {
|
|
140
140
|
// We set it to a valid state initially.
|
|
141
|
+
let isSupportedDstForBridge = true;
|
|
141
142
|
let isSameToken = true;
|
|
142
143
|
let isSameChain = false;
|
|
143
144
|
|
|
145
|
+
if (sourceChain && targetChain) {
|
|
146
|
+
isSupportedDstForBridge = !!sourceChain.supportedDstForBridge?.includes(
|
|
147
|
+
targetChain.chainId,
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
144
151
|
if (sourceToken && targetChain) {
|
|
145
152
|
// Bridge target chain is invalid when it doesn't have the same token available as selected in the source.
|
|
146
153
|
isSameToken = !!targetChain.tokens.find(
|
|
@@ -154,7 +161,7 @@ const isBridgeTargetValid = ({
|
|
|
154
161
|
isSameChain = sourceChain.chainId === targetChain.chainId;
|
|
155
162
|
}
|
|
156
163
|
|
|
157
|
-
return isSameToken && !isSameChain;
|
|
164
|
+
return isSameToken && !isSameChain && isSupportedDstForBridge;
|
|
158
165
|
};
|
|
159
166
|
|
|
160
167
|
type MapToValidPathParams = {
|
|
@@ -255,6 +262,13 @@ const mapToValidPathSwap = ({
|
|
|
255
262
|
}
|
|
256
263
|
|
|
257
264
|
// Setting tokens
|
|
265
|
+
// validate if the token is supported in the new source chain
|
|
266
|
+
newSourceToken = newSourceChain.tokens.find(
|
|
267
|
+
(token) => token.tokenId === newSourceToken?.tokenId && token.supported,
|
|
268
|
+
);
|
|
269
|
+
newTargetToken = newTargetChain.tokens.find(
|
|
270
|
+
(token) => token.tokenId === newTargetToken?.tokenId && token.supported,
|
|
271
|
+
);
|
|
258
272
|
|
|
259
273
|
if (!newSourceToken) {
|
|
260
274
|
newSourceToken = getDefaultSwapTokenForChain(
|
|
@@ -262,6 +276,7 @@ const mapToValidPathSwap = ({
|
|
|
262
276
|
DEFAULT_SOURCE_TOKEN_ADDR,
|
|
263
277
|
);
|
|
264
278
|
}
|
|
279
|
+
|
|
265
280
|
if (!newTargetToken || newSourceToken === newTargetToken) {
|
|
266
281
|
newTargetToken = getDefaultSwapTokenForChain(
|
|
267
282
|
newTargetChain,
|
|
@@ -315,10 +330,8 @@ const mapToValidPathBridge = ({
|
|
|
315
330
|
sourceToken: newSourceToken,
|
|
316
331
|
})
|
|
317
332
|
) {
|
|
318
|
-
newTargetChain = undefined;
|
|
319
333
|
// We can't have dangling token from a different chain.
|
|
320
334
|
newTargetToken = undefined;
|
|
321
|
-
|
|
322
335
|
if (
|
|
323
336
|
!isBridgeTargetValid({
|
|
324
337
|
sourceChain: newSourceChain,
|
|
@@ -326,22 +339,7 @@ const mapToValidPathBridge = ({
|
|
|
326
339
|
sourceToken: newSourceToken,
|
|
327
340
|
})
|
|
328
341
|
) {
|
|
329
|
-
|
|
330
|
-
console.error("[WRONG CONFIG] default bridge target chain is invalid.");
|
|
331
|
-
|
|
332
|
-
// Find any chain that is valid.
|
|
333
|
-
newTargetChain = supportedChains.find((chain) =>
|
|
334
|
-
isBridgeTargetValid({
|
|
335
|
-
sourceChain: newSourceChain,
|
|
336
|
-
targetChain: chain,
|
|
337
|
-
sourceToken: newSourceToken,
|
|
338
|
-
}),
|
|
339
|
-
);
|
|
340
|
-
if (!newTargetChain) {
|
|
341
|
-
throw new Error(
|
|
342
|
-
"mapToValidSwap > None of the chains supports bridge. Couldn't set target chain.",
|
|
343
|
-
);
|
|
344
|
-
}
|
|
342
|
+
newTargetChain = undefined;
|
|
345
343
|
}
|
|
346
344
|
}
|
|
347
345
|
|
|
@@ -365,7 +363,6 @@ const mapToValidPathBridge = ({
|
|
|
365
363
|
chain: newSourceChain,
|
|
366
364
|
bridgeTokensDictionary,
|
|
367
365
|
});
|
|
368
|
-
|
|
369
366
|
if (defaultToken && newSourceChain && newTargetChain) {
|
|
370
367
|
const isDefaultTokenBridgeable =
|
|
371
368
|
!!bridgeTokensDictionary[newSourceChain.chainId]?.[
|
|
@@ -375,9 +372,6 @@ const mapToValidPathBridge = ({
|
|
|
375
372
|
if (isDefaultTokenBridgeable) {
|
|
376
373
|
newSourceToken = defaultToken;
|
|
377
374
|
} else {
|
|
378
|
-
// This should never occur if our app is configured properly.
|
|
379
|
-
console.error("[WRONG CONFIG] default bridge source token is invalid.");
|
|
380
|
-
// Default is invalid, so let's keep it unset.
|
|
381
375
|
newSourceToken = undefined;
|
|
382
376
|
}
|
|
383
377
|
} else {
|
|
@@ -409,7 +403,7 @@ const mapToValidPathBridge = ({
|
|
|
409
403
|
}
|
|
410
404
|
}
|
|
411
405
|
|
|
412
|
-
if (!newTargetToken) {
|
|
406
|
+
if (!newTargetToken && newSourceToken) {
|
|
413
407
|
newTargetChain = undefined;
|
|
414
408
|
}
|
|
415
409
|
|
package/tailwind.config.js
CHANGED
|
@@ -64,6 +64,8 @@ export default {
|
|
|
64
64
|
"color-mix(in srgb, var(--error-dark) calc(<alpha-value> * 100%), transparent)",
|
|
65
65
|
t_error_light:
|
|
66
66
|
"color-mix(in srgb, var(--error-light) calc(<alpha-value> * 100%), transparent)",
|
|
67
|
+
t_chainlink_logo:
|
|
68
|
+
"color-mix(in srgb, var(--chainlink-logo) calc(<alpha-value> * 100%), transparent)",
|
|
67
69
|
|
|
68
70
|
x_alert: "rgb(255,183,77)",
|
|
69
71
|
x_alert_light: "rgb(255,226,183)",
|
|
@@ -260,6 +260,110 @@ describe("SwapProvider", () => {
|
|
|
260
260
|
// Should set a valid token for the new chain
|
|
261
261
|
expect(result.current.srcToken?.address).toBeDefined();
|
|
262
262
|
});
|
|
263
|
+
|
|
264
|
+
it("should preserve token when changing to chain with same token", async () => {
|
|
265
|
+
const { result } = renderHook(() => useSwapContext(), {
|
|
266
|
+
wrapper: getWrapper(
|
|
267
|
+
{ ...integrationConfig, bridge: false },
|
|
268
|
+
supportedChains,
|
|
269
|
+
wagmiConfig,
|
|
270
|
+
),
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
await act(async () => {
|
|
274
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// First set initial chain and token
|
|
278
|
+
const initialChain = supportedChains.find(
|
|
279
|
+
(chain) => chain.chainId === SRC_SWAP_CHAIN_ID,
|
|
280
|
+
);
|
|
281
|
+
if (!initialChain) throw new Error("Initial chain not found");
|
|
282
|
+
|
|
283
|
+
const initialToken = initialChain.tokens.find(
|
|
284
|
+
(token) =>
|
|
285
|
+
token.address.toLowerCase() === SRC_SWAP_TOKEN_ADDR.toLowerCase(),
|
|
286
|
+
);
|
|
287
|
+
if (!initialToken) throw new Error("Initial token not found");
|
|
288
|
+
|
|
289
|
+
await act(async () => {
|
|
290
|
+
result.current.setSrcChain(initialChain);
|
|
291
|
+
result.current.setSrcToken(initialToken);
|
|
292
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// Now change to a different chain that has the same token (by tokenId)
|
|
296
|
+
const newChain = supportedChains.find(
|
|
297
|
+
(chain) =>
|
|
298
|
+
chain.chainId !== initialChain.chainId &&
|
|
299
|
+
chain.tokens.some(
|
|
300
|
+
(token) =>
|
|
301
|
+
token.tokenId === initialToken.tokenId && token.supported,
|
|
302
|
+
),
|
|
303
|
+
);
|
|
304
|
+
if (!newChain) throw new Error("New chain with same token not found");
|
|
305
|
+
|
|
306
|
+
await act(async () => {
|
|
307
|
+
result.current.setSrcChain(newChain);
|
|
308
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// Should preserve the same tokenId but with new chain's token address
|
|
312
|
+
expect(result.current.srcToken?.tokenId).toBe(initialToken.tokenId);
|
|
313
|
+
expect(result.current.srcToken?.address).not.toBe(initialToken.address);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it("should reset token when changing to chain without same token", async () => {
|
|
317
|
+
const { result } = renderHook(() => useSwapContext(), {
|
|
318
|
+
wrapper: getWrapper(
|
|
319
|
+
{ ...integrationConfig, bridge: false },
|
|
320
|
+
supportedChains,
|
|
321
|
+
wagmiConfig,
|
|
322
|
+
),
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
await act(async () => {
|
|
326
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
// First set initial chain and token
|
|
330
|
+
const initialChain = supportedChains.find(
|
|
331
|
+
(chain) => chain.chainId === SRC_SWAP_CHAIN_ID,
|
|
332
|
+
);
|
|
333
|
+
if (!initialChain) throw new Error("Initial chain not found");
|
|
334
|
+
|
|
335
|
+
const initialToken = initialChain.tokens.find(
|
|
336
|
+
(token) =>
|
|
337
|
+
token.address.toLowerCase() === SRC_SWAP_TOKEN_ADDR.toLowerCase(),
|
|
338
|
+
);
|
|
339
|
+
if (!initialToken) throw new Error("Initial token not found");
|
|
340
|
+
|
|
341
|
+
await act(async () => {
|
|
342
|
+
result.current.setSrcChain(initialChain);
|
|
343
|
+
result.current.setSrcToken(initialToken);
|
|
344
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// Now change to a chain that doesn't have the same token
|
|
348
|
+
const newChain = supportedChains.find(
|
|
349
|
+
(chain) =>
|
|
350
|
+
chain.chainId !== initialChain.chainId &&
|
|
351
|
+
!chain.tokens.some((token) => token.tokenId === initialToken.tokenId),
|
|
352
|
+
);
|
|
353
|
+
if (!newChain) throw new Error("New chain without same token not found");
|
|
354
|
+
|
|
355
|
+
await act(async () => {
|
|
356
|
+
result.current.setSrcChain(newChain);
|
|
357
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// Should have a different token now
|
|
361
|
+
expect(result.current.srcToken?.tokenId).not.toBe(initialToken.tokenId);
|
|
362
|
+
expect(result.current.srcToken?.address).not.toBe(initialToken.address);
|
|
363
|
+
// But should still have a valid token
|
|
364
|
+
expect(result.current.srcToken).toBeDefined();
|
|
365
|
+
});
|
|
366
|
+
|
|
263
367
|
it("should handle destination chain change", async () => {
|
|
264
368
|
const { result } = renderHook(() => useSwapContext(), {
|
|
265
369
|
wrapper: getWrapper(
|
|
@@ -288,7 +392,7 @@ describe("SwapProvider", () => {
|
|
|
288
392
|
expect(result.current.dstToken?.address).toBeDefined();
|
|
289
393
|
});
|
|
290
394
|
|
|
291
|
-
it("should
|
|
395
|
+
it("should preserve token when changing destination chain with same token", async () => {
|
|
292
396
|
const { result } = renderHook(() => useSwapContext(), {
|
|
293
397
|
wrapper: getWrapper(
|
|
294
398
|
{ ...integrationConfig, bridge: false },
|
|
@@ -301,12 +405,119 @@ describe("SwapProvider", () => {
|
|
|
301
405
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
302
406
|
});
|
|
303
407
|
|
|
408
|
+
// First set initial chain and token
|
|
409
|
+
const initialChain = supportedChains.find(
|
|
410
|
+
(chain) => chain.chainId === DST_SWAP_CHAIN_ID,
|
|
411
|
+
);
|
|
412
|
+
if (!initialChain) throw new Error("Initial chain not found");
|
|
413
|
+
|
|
414
|
+
const initialToken = initialChain.tokens.find(
|
|
415
|
+
(token) =>
|
|
416
|
+
token.address.toLowerCase() === DST_SWAP_TOKEN_ADDR.toLowerCase(),
|
|
417
|
+
);
|
|
418
|
+
if (!initialToken) throw new Error("Initial token not found");
|
|
419
|
+
|
|
420
|
+
await act(async () => {
|
|
421
|
+
result.current.setDstChain(initialChain);
|
|
422
|
+
result.current.setDstToken(initialToken);
|
|
423
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
// Now change to a different chain that has the same token (by tokenId)
|
|
427
|
+
const newChain = supportedChains.find(
|
|
428
|
+
(chain) =>
|
|
429
|
+
chain.chainId !== initialChain.chainId &&
|
|
430
|
+
chain.tokens.some(
|
|
431
|
+
(token) =>
|
|
432
|
+
token.tokenId === initialToken.tokenId && token.supported,
|
|
433
|
+
),
|
|
434
|
+
);
|
|
435
|
+
if (!newChain) throw new Error("New chain with same token not found");
|
|
436
|
+
|
|
437
|
+
await act(async () => {
|
|
438
|
+
result.current.setDstChain(newChain);
|
|
439
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// Should preserve the same tokenId but with new chain's token address
|
|
443
|
+
expect(result.current.dstToken?.tokenId).toBe(initialToken.tokenId);
|
|
444
|
+
expect(result.current.dstToken?.address).not.toBe(initialToken.address);
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
it("should reset token when changing destination chain without same token", async () => {
|
|
448
|
+
const { result } = renderHook(() => useSwapContext(), {
|
|
449
|
+
wrapper: getWrapper(
|
|
450
|
+
{ ...integrationConfig, bridge: false },
|
|
451
|
+
supportedChains,
|
|
452
|
+
wagmiConfig,
|
|
453
|
+
),
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
await act(async () => {
|
|
457
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
// First set initial chain and token
|
|
461
|
+
const initialChain = supportedChains.find(
|
|
462
|
+
(chain) => chain.chainId === DST_SWAP_CHAIN_ID,
|
|
463
|
+
);
|
|
464
|
+
if (!initialChain) throw new Error("Initial chain not found");
|
|
465
|
+
|
|
466
|
+
const initialToken = initialChain.tokens.find(
|
|
467
|
+
(token) =>
|
|
468
|
+
token.address.toLowerCase() === DST_SWAP_TOKEN_ADDR.toLowerCase(),
|
|
469
|
+
);
|
|
470
|
+
if (!initialToken) throw new Error("Initial token not found");
|
|
471
|
+
|
|
472
|
+
await act(async () => {
|
|
473
|
+
result.current.setDstChain(initialChain);
|
|
474
|
+
result.current.setDstToken(initialToken);
|
|
475
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
// Now change to a chain that doesn't have the same token
|
|
304
479
|
const newChain = supportedChains.find(
|
|
480
|
+
(chain) =>
|
|
481
|
+
chain.chainId !== initialChain.chainId &&
|
|
482
|
+
!chain.tokens.some((token) => token.tokenId === initialToken.tokenId),
|
|
483
|
+
);
|
|
484
|
+
if (!newChain) throw new Error("New chain without same token not found");
|
|
485
|
+
|
|
486
|
+
await act(async () => {
|
|
487
|
+
result.current.setDstChain(newChain);
|
|
488
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
// Should have a different token now
|
|
492
|
+
expect(result.current.dstToken?.tokenId).not.toBe(initialToken.tokenId);
|
|
493
|
+
expect(result.current.dstToken?.address).not.toBe(initialToken.address);
|
|
494
|
+
// But should still have a valid token
|
|
495
|
+
expect(result.current.dstToken).toBeDefined();
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
it("should handle source token change", async () => {
|
|
499
|
+
const { result } = renderHook(() => useSwapContext(), {
|
|
500
|
+
wrapper: getWrapper(
|
|
501
|
+
{
|
|
502
|
+
...integrationConfig,
|
|
503
|
+
bridge: false,
|
|
504
|
+
srcChainId: SRC_SWAP_CHAIN_ID,
|
|
505
|
+
},
|
|
506
|
+
supportedChains,
|
|
507
|
+
wagmiConfig,
|
|
508
|
+
),
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
await act(async () => {
|
|
512
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
const activeSrcChain = supportedChains.find(
|
|
305
516
|
(chain) => chain.chainId === SRC_SWAP_CHAIN_ID,
|
|
306
517
|
);
|
|
307
|
-
if (!
|
|
518
|
+
if (!activeSrcChain) throw new Error("Source chain not set");
|
|
308
519
|
|
|
309
|
-
const newToken =
|
|
520
|
+
const newToken = activeSrcChain.tokens.find(
|
|
310
521
|
(token) =>
|
|
311
522
|
token.address.toLowerCase() === SRC_SWAP_TOKEN_ADDR.toLowerCase(),
|
|
312
523
|
);
|
|
@@ -322,7 +533,11 @@ describe("SwapProvider", () => {
|
|
|
322
533
|
it("should handle destination token change", async () => {
|
|
323
534
|
const { result } = renderHook(() => useSwapContext(), {
|
|
324
535
|
wrapper: getWrapper(
|
|
325
|
-
{
|
|
536
|
+
{
|
|
537
|
+
...integrationConfig,
|
|
538
|
+
bridge: false,
|
|
539
|
+
dstChainId: DST_SWAP_CHAIN_ID,
|
|
540
|
+
},
|
|
326
541
|
supportedChains,
|
|
327
542
|
wagmiConfig,
|
|
328
543
|
),
|
|
@@ -808,6 +1023,7 @@ describe("SwapProvider", () => {
|
|
|
808
1023
|
{
|
|
809
1024
|
...integrationConfig,
|
|
810
1025
|
bridge: true,
|
|
1026
|
+
srcChainId: SRC_BRIDGE_CHAIN_ID,
|
|
811
1027
|
dstChainId: INVALID_DST_BRIDGE_CHAIN_ID,
|
|
812
1028
|
},
|
|
813
1029
|
supportedChains,
|