@xswap-link/sdk 0.9.0 → 0.9.2
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/dist/index.d.mts +8 -4
- package/dist/index.d.ts +8 -4
- package/dist/index.global.js +92 -683
- package/dist/index.js +7 -7
- package/dist/index.mjs +9 -9
- package/package.json +3 -1
- package/src/components/Swap/SwapView/SwapButton/index.tsx +13 -5
- package/src/components/Swap/SwapView/SwapPanel/ChainPanel/ChainPicker/ChainItem/index.tsx +51 -59
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/TokenItem/index.tsx +36 -11
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/index.tsx +26 -6
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/index.tsx +5 -1
- package/src/components/Swap/SwapView/SwapPanel/index.tsx +1 -1
- package/src/components/Swap/SwapView/index.tsx +2 -2
- package/src/components/Tooltip/index.tsx +1 -1
- package/src/components/TxConfigForm/index.tsx +8 -1
- package/src/components/TxWidgetWC/index.tsx +2 -0
- package/src/components/TxWidgetWCWrapped/index.tsx +3 -0
- package/src/config/wagmiConfig.ts +7 -5
- package/src/context/SwapProvider.tsx +45 -38
- package/src/models/TokenData.ts +3 -1
- package/src/models/payloads/GetPricesPayload.ts +1 -1
- package/src/models/payloads/ModalIntegrationPayload.ts +1 -0
- package/src/models/payloads/WidgetIntegrationPayload.ts +1 -0
- package/src/types/global.d.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xswap-link/sdk",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "JavaScript SDK for XSwap platform",
|
|
5
5
|
"homepage": "https://github.com/xswap-link/xswap-sdk",
|
|
6
6
|
"repository": {
|
|
@@ -36,6 +36,8 @@
|
|
|
36
36
|
"@fortawesome/react-fontawesome": "^0.2.0",
|
|
37
37
|
"@r2wc/core": "^1.1.0",
|
|
38
38
|
"@tanstack/react-query": "^5.64.2",
|
|
39
|
+
"@wagmi/connectors": "^5.7.5",
|
|
40
|
+
"@wagmi/core": "^2.16.3",
|
|
39
41
|
"async-retry": "^1.3.3",
|
|
40
42
|
"bignumber.js": "4.0.4",
|
|
41
43
|
"date-fns": "^3.6.0",
|
|
@@ -34,6 +34,8 @@ export const SwapButton = () => {
|
|
|
34
34
|
srcTokenBalanceWei,
|
|
35
35
|
isFetchingRoute,
|
|
36
36
|
isAsyncDataLoaded,
|
|
37
|
+
hasOnConnectWalletCallback,
|
|
38
|
+
onConnectWallet,
|
|
37
39
|
} = useSwapContext();
|
|
38
40
|
|
|
39
41
|
const { setTxStatus, setTxMsg, setTxModalOpen, enqueueTransaction } =
|
|
@@ -111,13 +113,19 @@ export const SwapButton = () => {
|
|
|
111
113
|
|
|
112
114
|
if (!address) {
|
|
113
115
|
return {
|
|
114
|
-
text:
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
text:
|
|
117
|
+
integrationConfig.defaultWalletPicker || hasOnConnectWalletCallback
|
|
118
|
+
? "Connect Wallet"
|
|
119
|
+
: "Connect Wallet First",
|
|
117
120
|
fn: () => {
|
|
118
|
-
|
|
121
|
+
if (integrationConfig.defaultWalletPicker) {
|
|
122
|
+
setConnectWalletModalOpen(true);
|
|
123
|
+
} else if (hasOnConnectWalletCallback) {
|
|
124
|
+
onConnectWallet();
|
|
125
|
+
}
|
|
119
126
|
},
|
|
120
|
-
disabled:
|
|
127
|
+
disabled:
|
|
128
|
+
!integrationConfig.defaultWalletPicker && !hasOnConnectWalletCallback,
|
|
121
129
|
};
|
|
122
130
|
}
|
|
123
131
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { DotGreenIcon
|
|
1
|
+
import { DotGreenIcon } from "@src/assets/icons";
|
|
2
2
|
import { SwapPanelType } from "@src/components/Swap/SwapView";
|
|
3
|
-
import { Tooltip } from "@src/components/Tooltip";
|
|
4
3
|
import { useSwapContext } from "@src/context";
|
|
5
4
|
import useNetworks from "@src/hooks/networkManagement/useNetworks";
|
|
6
5
|
import { Chain } from "@src/models";
|
|
7
|
-
import { useMemo
|
|
6
|
+
import { useMemo } from "react";
|
|
8
7
|
|
|
9
8
|
type Props = {
|
|
10
9
|
chain: Chain;
|
|
@@ -18,8 +17,6 @@ export const ChainItem = ({ chain, type, onClick, disabled }: Props) => {
|
|
|
18
17
|
networks: { evm },
|
|
19
18
|
} = useNetworks();
|
|
20
19
|
|
|
21
|
-
const tooltipTriggerRef = useRef<SVGSVGElement>(null);
|
|
22
|
-
|
|
23
20
|
const { srcChain, dstChain, bridgeUI } = useSwapContext();
|
|
24
21
|
|
|
25
22
|
const currentChainId = useMemo(
|
|
@@ -40,66 +37,61 @@ export const ChainItem = ({ chain, type, onClick, disabled }: Props) => {
|
|
|
40
37
|
return type === "destination" ? srcChain?.chainId : dstChain?.chainId;
|
|
41
38
|
}, [bridgeUI, dstChain?.chainId, srcChain?.chainId, type]);
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
: ""
|
|
57
|
-
}`}
|
|
58
|
-
>
|
|
59
|
-
<div className="flex gap-3 items-center w-full">
|
|
60
|
-
<img src={chain.image} alt={chain.name} className="w-[34px] h-[34px]" />
|
|
61
|
-
<p>{chain.displayName}</p>
|
|
62
|
-
</div>
|
|
40
|
+
const getTooltipText = () => {
|
|
41
|
+
if (chain.chainId === sameChainId) {
|
|
42
|
+
return "Transfers between the same chains are not available";
|
|
43
|
+
}
|
|
44
|
+
if (disabled) {
|
|
45
|
+
return bridgeUI
|
|
46
|
+
? "Token is not available on this chain"
|
|
47
|
+
: `Swap from ${
|
|
48
|
+
srcChain?.displayName || "the source chain"
|
|
49
|
+
} to this chain is currently not supported.`;
|
|
50
|
+
}
|
|
51
|
+
return "";
|
|
52
|
+
};
|
|
63
53
|
|
|
64
|
-
|
|
65
|
-
<div className="flex items-baseline gap-1">
|
|
66
|
-
<DotGreenIcon />
|
|
67
|
-
<div className="text-t_text_green">connected</div>
|
|
68
|
-
</div>
|
|
69
|
-
)}
|
|
54
|
+
const tooltipText = getTooltipText();
|
|
70
55
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
56
|
+
return (
|
|
57
|
+
<div className="group relative">
|
|
58
|
+
<div
|
|
59
|
+
onClick={() => {
|
|
60
|
+
if (chain.chainId === sameChainId || disabled) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
onClick(chain.chainId);
|
|
64
|
+
}}
|
|
65
|
+
className={`flex justify-between items-center gap-2 mt-2 mb-2 cursor-pointer p-4 border border-solid border-white border-opacity-0 hover:selected-chain-item ${
|
|
66
|
+
currentChainId === chain.chainId ? "selected-chain-item" : ""
|
|
67
|
+
} ${
|
|
68
|
+
chain.chainId === sameChainId || disabled
|
|
69
|
+
? "disabled-chain-item cursor-default"
|
|
70
|
+
: ""
|
|
71
|
+
}`}
|
|
72
|
+
>
|
|
73
|
+
<div className="flex gap-3 items-center w-full">
|
|
74
|
+
<img
|
|
75
|
+
src={chain.image}
|
|
76
|
+
alt={chain.name}
|
|
77
|
+
className="w-[34px] h-[34px]"
|
|
84
78
|
/>
|
|
79
|
+
<p>{chain.displayName}</p>
|
|
85
80
|
</div>
|
|
86
|
-
)}
|
|
87
81
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
position="BOTTOM"
|
|
94
|
-
triggerRef={tooltipTriggerRef}
|
|
95
|
-
/>
|
|
96
|
-
</div>
|
|
97
|
-
)}
|
|
82
|
+
{tooltipText && (
|
|
83
|
+
<div className="w-full text-center opacity-0 group-hover:opacity-100 text-xs transition-opacity duration-200">
|
|
84
|
+
{tooltipText}
|
|
85
|
+
</div>
|
|
86
|
+
)}
|
|
98
87
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
88
|
+
{connected && (
|
|
89
|
+
<div className="flex items-baseline gap-1">
|
|
90
|
+
<DotGreenIcon />
|
|
91
|
+
<div className="text-t_text_green">connected</div>
|
|
92
|
+
</div>
|
|
93
|
+
)}
|
|
94
|
+
</div>
|
|
103
95
|
</div>
|
|
104
96
|
);
|
|
105
97
|
};
|
|
@@ -18,7 +18,7 @@ export const TokenItem = ({
|
|
|
18
18
|
onClick,
|
|
19
19
|
selectedChainId,
|
|
20
20
|
}: Props) => {
|
|
21
|
-
const { supportedChains } = useSwapContext();
|
|
21
|
+
const { supportedChains, tokenPrices } = useSwapContext();
|
|
22
22
|
const { address } = useAccount();
|
|
23
23
|
|
|
24
24
|
const chain = useMemo(
|
|
@@ -26,6 +26,26 @@ export const TokenItem = ({
|
|
|
26
26
|
[supportedChains, token],
|
|
27
27
|
);
|
|
28
28
|
|
|
29
|
+
const tokenPrice = useMemo(() => {
|
|
30
|
+
const prices = tokenPrices[token.chainId];
|
|
31
|
+
return prices?.[token.address];
|
|
32
|
+
}, [token, tokenPrices]);
|
|
33
|
+
|
|
34
|
+
const tokenBalance = useMemo(() => {
|
|
35
|
+
if (!token.balance || !token.decimals) return null;
|
|
36
|
+
return Number(ethers.utils.formatUnits(token.balance, token.decimals));
|
|
37
|
+
}, [token.balance, token.decimals]);
|
|
38
|
+
|
|
39
|
+
const hasBalance = useMemo(
|
|
40
|
+
() => token.balance && !token.balance.eq(0),
|
|
41
|
+
[token.balance],
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const tokenValueUsd = useMemo(() => {
|
|
45
|
+
if (!tokenBalance || !tokenPrice || !hasBalance) return null;
|
|
46
|
+
return tokenBalance * +tokenPrice;
|
|
47
|
+
}, [tokenBalance, tokenPrice, hasBalance]);
|
|
48
|
+
|
|
29
49
|
return (
|
|
30
50
|
<div
|
|
31
51
|
className={`token-picker-container ${
|
|
@@ -55,16 +75,21 @@ export const TokenItem = ({
|
|
|
55
75
|
</div>
|
|
56
76
|
|
|
57
77
|
{token.balance && token.decimals ? (
|
|
58
|
-
<div className="text-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
78
|
+
<div className="text-right">
|
|
79
|
+
<div className="text-xs text-t_text_primary">
|
|
80
|
+
{token.balance.eq(0) || tokenBalance! > 0.0001
|
|
81
|
+
? weiToHumanReadable({
|
|
82
|
+
amount: token.balance.toString(),
|
|
83
|
+
decimals: token.decimals,
|
|
84
|
+
precisionFractionalPlaces: 4,
|
|
85
|
+
})
|
|
86
|
+
: "<0.0001"}
|
|
87
|
+
</div>
|
|
88
|
+
{hasBalance && (
|
|
89
|
+
<div className="text-xs text-t_text_primary text-opacity-50">
|
|
90
|
+
{tokenValueUsd ? `$${tokenValueUsd.toFixed(2)}` : "$ -"}
|
|
91
|
+
</div>
|
|
92
|
+
)}
|
|
68
93
|
</div>
|
|
69
94
|
) : (
|
|
70
95
|
<>
|
|
@@ -51,8 +51,12 @@ export const TokenPicker = ({
|
|
|
51
51
|
const currentRouteRequestNonce = useRef<number>(0);
|
|
52
52
|
const tokenSearchRef = useRef<HTMLInputElement | null>(null);
|
|
53
53
|
|
|
54
|
-
const {
|
|
55
|
-
|
|
54
|
+
const {
|
|
55
|
+
bridgeUI,
|
|
56
|
+
supportedChains,
|
|
57
|
+
findTokenDataByAddressAndChain,
|
|
58
|
+
tokenPrices,
|
|
59
|
+
} = useSwapContext();
|
|
56
60
|
const { address } = useAccount();
|
|
57
61
|
const evmContractApi = useEvmContractApi();
|
|
58
62
|
|
|
@@ -191,6 +195,15 @@ export const TokenPicker = ({
|
|
|
191
195
|
}, [isOpen]);
|
|
192
196
|
|
|
193
197
|
const allTokens = useMemo(() => {
|
|
198
|
+
const calculateTokenValue = (token: TokenOption) => {
|
|
199
|
+
if (!token.balance || !token.decimals) return 0;
|
|
200
|
+
const balance = Number(
|
|
201
|
+
ethers.utils.formatUnits(token.balance, token.decimals),
|
|
202
|
+
);
|
|
203
|
+
const price = tokenPrices[token.chainId]?.[token.address];
|
|
204
|
+
return price ? balance * Number(price) : 0;
|
|
205
|
+
};
|
|
206
|
+
|
|
194
207
|
const ownedFilteredTokens = [
|
|
195
208
|
...filteredTokens.filter((token) =>
|
|
196
209
|
BigNumber.from(token?.balance || "0").gt(0),
|
|
@@ -198,9 +211,16 @@ export const TokenPicker = ({
|
|
|
198
211
|
...otherFilteredTokens.filter((token) =>
|
|
199
212
|
BigNumber.from(token?.balance || "0").gt(0),
|
|
200
213
|
),
|
|
201
|
-
].sort(
|
|
202
|
-
|
|
203
|
-
|
|
214
|
+
].sort((tokenA, tokenB) => {
|
|
215
|
+
const valueA = calculateTokenValue(tokenA);
|
|
216
|
+
const valueB = calculateTokenValue(tokenB);
|
|
217
|
+
// First sort by USD value
|
|
218
|
+
if (valueB !== valueA) {
|
|
219
|
+
return valueB - valueA;
|
|
220
|
+
}
|
|
221
|
+
// If USD values are equal (or both 0), sort by priority
|
|
222
|
+
return tokenB.priority - tokenA.priority;
|
|
223
|
+
});
|
|
204
224
|
|
|
205
225
|
const currentChainTokens = filteredTokens
|
|
206
226
|
.filter((token) => BigNumber.from(token?.balance || "0").eq(0))
|
|
@@ -231,7 +251,7 @@ export const TokenPicker = ({
|
|
|
231
251
|
];
|
|
232
252
|
|
|
233
253
|
return groups.flat();
|
|
234
|
-
}, [filteredTokens, otherFilteredTokens, chain, address]);
|
|
254
|
+
}, [filteredTokens, otherFilteredTokens, chain, address, tokenPrices]);
|
|
235
255
|
|
|
236
256
|
const ownedTokens = useMemo(
|
|
237
257
|
() => allTokens.filter((token) => token.balance?.gt(0)),
|
|
@@ -113,7 +113,11 @@ export const TokenPanel = ({ chain, token, type, className }: Props) => {
|
|
|
113
113
|
<div className="flex flex-col font-medium items-start">
|
|
114
114
|
<p className="text-xs opacity-60">Token: </p>
|
|
115
115
|
<p className={`${token ? "" : "opacity-60"}`}>
|
|
116
|
-
{token
|
|
116
|
+
{token
|
|
117
|
+
? token.symbol
|
|
118
|
+
: type === "destination" && bridgeUI
|
|
119
|
+
? "-"
|
|
120
|
+
: "Select"}
|
|
117
121
|
</p>
|
|
118
122
|
</div>
|
|
119
123
|
</div>
|
|
@@ -38,7 +38,7 @@ export const SwapPanel = ({ type }: Props) => {
|
|
|
38
38
|
/>
|
|
39
39
|
</div>
|
|
40
40
|
<div
|
|
41
|
-
className={`flex justify-between ${
|
|
41
|
+
className={`flex justify-between rounded-b-[11px] ${
|
|
42
42
|
type === "destination" &&
|
|
43
43
|
"bg-gradient-to-r from-t_main_accent_light/20 to-t_main_accent_dark/20"
|
|
44
44
|
}`}
|
|
@@ -7,8 +7,8 @@ export type SwapPanelType = "source" | "destination";
|
|
|
7
7
|
|
|
8
8
|
export const SwapView = () => {
|
|
9
9
|
return (
|
|
10
|
-
<div className="flex flex-col gap-
|
|
11
|
-
<div className="flex flex-col gap-[
|
|
10
|
+
<div className="flex flex-col gap-6 fill-t_text_primary">
|
|
11
|
+
<div className="flex flex-col gap-[11px]">
|
|
12
12
|
<SwapPanel type="source" />
|
|
13
13
|
<ReorderButton />
|
|
14
14
|
<SwapPanel type="destination" />
|
|
@@ -13,7 +13,7 @@ const positionToClass: Record<Position, string> = {
|
|
|
13
13
|
|
|
14
14
|
export const Tooltip: FC<{
|
|
15
15
|
id: string;
|
|
16
|
-
position:
|
|
16
|
+
position: Position;
|
|
17
17
|
text: string;
|
|
18
18
|
triggerRef: RefObject<Element>;
|
|
19
19
|
}> = ({ id, position, text, triggerRef }) => {
|
|
@@ -32,9 +32,14 @@ const WagmiReload: FC = () => {
|
|
|
32
32
|
const { reconnect } = useReconnect();
|
|
33
33
|
|
|
34
34
|
useEffect(() => {
|
|
35
|
+
let count = 0;
|
|
35
36
|
const interval = setInterval(() => {
|
|
36
37
|
reconnect();
|
|
37
|
-
|
|
38
|
+
count++;
|
|
39
|
+
if (count >= 5) {
|
|
40
|
+
clearInterval(interval);
|
|
41
|
+
}
|
|
42
|
+
}, 1000);
|
|
38
43
|
|
|
39
44
|
return () => {
|
|
40
45
|
clearInterval(interval);
|
|
@@ -91,6 +96,7 @@ export const TxConfigForm = ({
|
|
|
91
96
|
onSrcTokenChange,
|
|
92
97
|
onSrcChainChange,
|
|
93
98
|
bridge,
|
|
99
|
+
onConnectWallet,
|
|
94
100
|
}: TxConfigFormPayload &
|
|
95
101
|
(
|
|
96
102
|
| {
|
|
@@ -156,6 +162,7 @@ export const TxConfigForm = ({
|
|
|
156
162
|
onSrcTokenChange,
|
|
157
163
|
onSrcChainChange,
|
|
158
164
|
bridge,
|
|
165
|
+
onConnectWallet,
|
|
159
166
|
}}
|
|
160
167
|
supportedChains={supportedChains}
|
|
161
168
|
wagmiConfig={wagmiConfig}
|
|
@@ -33,6 +33,7 @@ const TxWidget = ({
|
|
|
33
33
|
onDstChainChange,
|
|
34
34
|
onSrcTokenChange,
|
|
35
35
|
onSrcChainChange,
|
|
36
|
+
onConnectWallet,
|
|
36
37
|
bridge,
|
|
37
38
|
}: WidgetIntegrationPayload) => {
|
|
38
39
|
const [loading, setLoading] = useState(true);
|
|
@@ -95,6 +96,7 @@ const TxWidget = ({
|
|
|
95
96
|
onDstChainChange={onDstChainChange}
|
|
96
97
|
onSrcTokenChange={onSrcTokenChange}
|
|
97
98
|
onSrcChainChange={onSrcChainChange}
|
|
99
|
+
onConnectWallet={onConnectWallet}
|
|
98
100
|
bridge={bridge}
|
|
99
101
|
/>
|
|
100
102
|
)}
|
|
@@ -45,6 +45,7 @@ export const TxWidgetWCWrapped = ({
|
|
|
45
45
|
onDstChainChange,
|
|
46
46
|
onSrcTokenChange,
|
|
47
47
|
onSrcChainChange,
|
|
48
|
+
onConnectWallet,
|
|
48
49
|
bridge,
|
|
49
50
|
}: WidgetIntegrationPayload) => {
|
|
50
51
|
useEffect(() => {
|
|
@@ -55,12 +56,14 @@ export const TxWidgetWCWrapped = ({
|
|
|
55
56
|
window.xPayOnDstChainChange = onDstChainChange;
|
|
56
57
|
window.xPayOnSrcTokenChange = onSrcTokenChange;
|
|
57
58
|
window.xPayOnSrcChainChange = onSrcChainChange;
|
|
59
|
+
window.xPayOnConnectWallet = onConnectWallet;
|
|
58
60
|
}, [
|
|
59
61
|
onPendingTransactionsChange,
|
|
60
62
|
onDstTokenChange,
|
|
61
63
|
onDstChainChange,
|
|
62
64
|
onSrcTokenChange,
|
|
63
65
|
onSrcChainChange,
|
|
66
|
+
onConnectWallet,
|
|
64
67
|
]);
|
|
65
68
|
|
|
66
69
|
return (
|
|
@@ -3,8 +3,8 @@ import { isServer } from "@src/utils";
|
|
|
3
3
|
import { Transport } from "viem";
|
|
4
4
|
import * as WagmiChains from "viem/chains";
|
|
5
5
|
import { mainnet } from "viem/chains";
|
|
6
|
-
import { Config, createConfig, createStorage, http } from "wagmi";
|
|
7
|
-
import { injected,
|
|
6
|
+
import { Config, createConfig, createStorage, http } from "@wagmi/core";
|
|
7
|
+
import { injected, walletConnect, coinbaseWallet } from "@wagmi/connectors";
|
|
8
8
|
|
|
9
9
|
const storage = createStorage({
|
|
10
10
|
key: "xpay.wagmi.store",
|
|
@@ -19,11 +19,13 @@ export const getWagmiConfig = (supportedChains: Chain[]): Config => {
|
|
|
19
19
|
transports,
|
|
20
20
|
connectors: [
|
|
21
21
|
injected(),
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
coinbaseWallet({
|
|
23
|
+
appLogoUrl: "https://xswap.link/favicon.ico",
|
|
24
|
+
appName: "XSwap",
|
|
25
|
+
}),
|
|
24
26
|
walletConnect({
|
|
25
27
|
projectId: "c392898b45ac587a280b5eb33e92aeb0",
|
|
26
|
-
showQrModal:
|
|
28
|
+
showQrModal: true,
|
|
27
29
|
}),
|
|
28
30
|
],
|
|
29
31
|
storage,
|
|
@@ -64,8 +64,7 @@ type SwapContext = {
|
|
|
64
64
|
setSrcChain: Dispatch<SetStateAction<Chain | undefined>>;
|
|
65
65
|
srcChainTokensOptions: TokenOption[];
|
|
66
66
|
srcChainOtherTokensOptions: TokenOption[];
|
|
67
|
-
|
|
68
|
-
dstChainTokensPrices: TokenPrices;
|
|
67
|
+
tokenPrices: TokenPrices;
|
|
69
68
|
srcToken: Token | undefined;
|
|
70
69
|
setSrcToken: Dispatch<SetStateAction<Token | undefined>>;
|
|
71
70
|
dstChain: Chain | undefined;
|
|
@@ -110,6 +109,8 @@ type SwapContext = {
|
|
|
110
109
|
chainId: string,
|
|
111
110
|
) => Token | undefined;
|
|
112
111
|
bridgeTokensDictionary: BridgeTokensDictionary | null;
|
|
112
|
+
onConnectWallet: () => void;
|
|
113
|
+
hasOnConnectWalletCallback: boolean;
|
|
113
114
|
};
|
|
114
115
|
|
|
115
116
|
const functionNotImplemented = () => {
|
|
@@ -128,8 +129,7 @@ const init: SwapContext = {
|
|
|
128
129
|
srcChain: undefined,
|
|
129
130
|
srcChainTokensOptions: [],
|
|
130
131
|
srcChainOtherTokensOptions: [],
|
|
131
|
-
|
|
132
|
-
dstChainTokensPrices: {},
|
|
132
|
+
tokenPrices: {},
|
|
133
133
|
dstChain: undefined,
|
|
134
134
|
dstChainTokensOptions: [],
|
|
135
135
|
dstChainOtherTokensOptions: [],
|
|
@@ -174,6 +174,8 @@ const init: SwapContext = {
|
|
|
174
174
|
refreshBalance: functionNotImplemented,
|
|
175
175
|
findTokenDataByAddressAndChain: functionNotImplemented,
|
|
176
176
|
bridgeTokensDictionary: null,
|
|
177
|
+
onConnectWallet: functionNotImplemented,
|
|
178
|
+
hasOnConnectWalletCallback: false,
|
|
177
179
|
};
|
|
178
180
|
|
|
179
181
|
const swapContext = createContext(init);
|
|
@@ -246,12 +248,7 @@ export const SwapProvider = ({
|
|
|
246
248
|
const [dstChainTokensOptions, setDstChainTokensOptions] = useState(
|
|
247
249
|
init.dstChainTokensOptions,
|
|
248
250
|
);
|
|
249
|
-
const [
|
|
250
|
-
init.srcChainTokensPrices,
|
|
251
|
-
);
|
|
252
|
-
const [dstChainTokensPrices, setDstChainTokensPrices] = useState(
|
|
253
|
-
init.dstChainTokensPrices,
|
|
254
|
-
);
|
|
251
|
+
const [tokenPrices, setTokenPrices] = useState(init.tokenPrices);
|
|
255
252
|
const [srcChainOtherTokensOptions, setSrcChainOtherTokensOptions] = useState(
|
|
256
253
|
init.srcChainOtherTokensOptions,
|
|
257
254
|
);
|
|
@@ -265,6 +262,15 @@ export const SwapProvider = ({
|
|
|
265
262
|
|
|
266
263
|
const { history } = useHistory();
|
|
267
264
|
|
|
265
|
+
useEffect(() => {
|
|
266
|
+
if (supportedChains.length > 0) {
|
|
267
|
+
const chainIds = supportedChains.map((chain) => chain.chainId);
|
|
268
|
+
getPrices({ chainId: chainIds }).then((prices) => {
|
|
269
|
+
setTokenPrices(prices);
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}, [supportedChains]);
|
|
273
|
+
|
|
268
274
|
const supportedTokens: Record<string, Record<string, Token>> = useMemo(() => {
|
|
269
275
|
const customTokens = !isServer
|
|
270
276
|
? JSON.parse(localStorage.getItem("custom-tokens") || "{}")
|
|
@@ -406,36 +412,21 @@ export const SwapProvider = ({
|
|
|
406
412
|
[srcToken?.decimals, srcValue],
|
|
407
413
|
);
|
|
408
414
|
|
|
409
|
-
// fetch srcTokenPrices
|
|
410
|
-
useEffect(() => {
|
|
411
|
-
if (srcChain) {
|
|
412
|
-
getPrices({ chainId: srcChain.chainId, currency: "USD" }).then((prices) =>
|
|
413
|
-
setSrcChainTokensPrices(prices),
|
|
414
|
-
);
|
|
415
|
-
}
|
|
416
|
-
}, [srcChain]);
|
|
417
|
-
|
|
418
|
-
// fetch dstTokenPrices
|
|
419
|
-
useEffect(() => {
|
|
420
|
-
if (dstChain) {
|
|
421
|
-
getPrices({ chainId: dstChain.chainId, currency: "USD" }).then((prices) =>
|
|
422
|
-
setDstChainTokensPrices(prices),
|
|
423
|
-
);
|
|
424
|
-
}
|
|
425
|
-
}, [dstChain]);
|
|
426
|
-
|
|
427
415
|
const srcValueUsd = useMemo(() => {
|
|
428
416
|
if (
|
|
429
417
|
srcToken &&
|
|
430
|
-
|
|
431
|
-
|
|
418
|
+
srcChain &&
|
|
419
|
+
tokenPrices &&
|
|
420
|
+
tokenPrices[srcChain.chainId] &&
|
|
421
|
+
tokenPrices[srcChain.chainId]?.[srcToken.address]
|
|
432
422
|
) {
|
|
433
423
|
return (
|
|
434
|
-
Number(srcValue) *
|
|
424
|
+
Number(srcValue) *
|
|
425
|
+
Number(tokenPrices[srcChain.chainId]?.[srcToken.address])
|
|
435
426
|
).toFixed(2);
|
|
436
427
|
}
|
|
437
428
|
return null;
|
|
438
|
-
}, [
|
|
429
|
+
}, [tokenPrices, srcToken, srcValue, srcChain]);
|
|
439
430
|
const dstValue = useMemo(
|
|
440
431
|
() =>
|
|
441
432
|
weiToHumanReadable({
|
|
@@ -457,15 +448,18 @@ export const SwapProvider = ({
|
|
|
457
448
|
const dstValueUsd = useMemo(() => {
|
|
458
449
|
if (
|
|
459
450
|
dstToken &&
|
|
460
|
-
|
|
461
|
-
|
|
451
|
+
dstChain &&
|
|
452
|
+
tokenPrices &&
|
|
453
|
+
tokenPrices[dstChain?.chainId] &&
|
|
454
|
+
tokenPrices[dstChain?.chainId]?.[dstToken.address]
|
|
462
455
|
) {
|
|
463
456
|
return (
|
|
464
|
-
Number(dstValue) *
|
|
457
|
+
Number(dstValue) *
|
|
458
|
+
Number(tokenPrices[dstChain?.chainId]?.[dstToken.address])
|
|
465
459
|
).toFixed(2);
|
|
466
460
|
}
|
|
467
461
|
return null;
|
|
468
|
-
}, [
|
|
462
|
+
}, [tokenPrices, dstToken, dstValue, dstChain]);
|
|
469
463
|
const dstValueMin = useMemo(
|
|
470
464
|
() =>
|
|
471
465
|
weiToHumanReadable({
|
|
@@ -933,6 +927,18 @@ export const SwapProvider = ({
|
|
|
933
927
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
934
928
|
}, [integrationConfig.onSrcTokenChange, srcToken]);
|
|
935
929
|
|
|
930
|
+
const onConnectWallet = useCallback(() => {
|
|
931
|
+
if (integrationConfig.onConnectWallet) {
|
|
932
|
+
integrationConfig.onConnectWallet();
|
|
933
|
+
} else if (window.xPayOnConnectWallet) {
|
|
934
|
+
window.xPayOnConnectWallet();
|
|
935
|
+
}
|
|
936
|
+
}, [integrationConfig]);
|
|
937
|
+
|
|
938
|
+
const hasOnConnectWalletCallback = useMemo(() => {
|
|
939
|
+
return !!(integrationConfig.onConnectWallet || window.xPayOnConnectWallet);
|
|
940
|
+
}, [integrationConfig.onConnectWallet]);
|
|
941
|
+
|
|
936
942
|
return (
|
|
937
943
|
<swapContext.Provider
|
|
938
944
|
value={{
|
|
@@ -950,8 +956,7 @@ export const SwapProvider = ({
|
|
|
950
956
|
setSrcChain,
|
|
951
957
|
srcChainTokensOptions,
|
|
952
958
|
srcChainOtherTokensOptions,
|
|
953
|
-
|
|
954
|
-
srcChainTokensPrices,
|
|
959
|
+
tokenPrices,
|
|
955
960
|
dstChain,
|
|
956
961
|
setDstChain,
|
|
957
962
|
dstChainTokensOptions,
|
|
@@ -993,6 +998,8 @@ export const SwapProvider = ({
|
|
|
993
998
|
dstTokenLocked,
|
|
994
999
|
dstChainLocked,
|
|
995
1000
|
bridgeTokensDictionary,
|
|
1001
|
+
onConnectWallet,
|
|
1002
|
+
hasOnConnectWalletCallback,
|
|
996
1003
|
}}
|
|
997
1004
|
>
|
|
998
1005
|
{children}
|
package/src/models/TokenData.ts
CHANGED