@xswap-link/sdk 0.2.2 → 0.2.4
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 +15 -0
- package/dist/index.css +7 -14
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +466 -388
- package/dist/index.mjs +405 -327
- package/package.json +1 -1
- package/src/components/TxConfigForm/FeesDetails.tsx +44 -30
- package/src/components/TxConfigForm/Form.tsx +9 -2
- package/src/components/TxConfigForm/Summary.tsx +15 -10
- package/src/components/TxConfigForm/SwapPanel.tsx +4 -0
- package/src/components/TxConfigForm/TopBar.tsx +8 -3
- package/src/components/TxConfigForm/UsdPrice.tsx +14 -1
- package/src/components/TxConfigForm/index.tsx +5 -10
- package/src/components/WaitingForInit/index.tsx +20 -0
- package/src/config/init.tsx +75 -0
- package/src/constants/index.ts +1 -0
- package/src/models/Route.ts +6 -2
- package/src/utils/contracts.ts +2 -4
- package/tailwind.config.js +2 -2
- package/src/config/init.ts +0 -31
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@ import { FC } from "react";
|
|
|
2
2
|
import { CoinsIcon, TimerIcon, ChevronUpIcon, ChevronDownIcon } from "../icons";
|
|
3
3
|
import { safeBigNumberFrom, weiToHumanReadable } from "@src/utils";
|
|
4
4
|
import { Route, Token } from "@src/models";
|
|
5
|
+
import { Skeleton } from "@src/components";
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
7
8
|
route: Route | undefined;
|
|
@@ -9,6 +10,7 @@ interface Props {
|
|
|
9
10
|
paymentToken: Token | undefined;
|
|
10
11
|
dstToken: Token | undefined;
|
|
11
12
|
expressChecked: boolean;
|
|
13
|
+
exceedsExpressDeliveryLimit: boolean;
|
|
12
14
|
slippage: string | undefined;
|
|
13
15
|
feesDetailsShown: boolean;
|
|
14
16
|
setFeesDetailsShown: React.Dispatch<React.SetStateAction<boolean>>;
|
|
@@ -20,18 +22,19 @@ export const FeesDetails: FC<Props> = ({
|
|
|
20
22
|
paymentToken,
|
|
21
23
|
dstToken,
|
|
22
24
|
expressChecked,
|
|
25
|
+
exceedsExpressDeliveryLimit,
|
|
23
26
|
slippage,
|
|
24
27
|
feesDetailsShown,
|
|
25
28
|
setFeesDetailsShown,
|
|
26
29
|
}) => {
|
|
27
30
|
return (
|
|
28
|
-
<div className="flex flex-col gap-3 globalBorder rounded-lg bg-[rgba(15,15,15,1)] p-4 mb-1">
|
|
29
|
-
<div className="flex w-full items-center justify-between text-xs sm:text-sm
|
|
31
|
+
<div className="flex flex-col gap-3 globalBorder rounded-lg bg-[rgba(15,15,15,1)] p-2 sm:p-4 mb-1">
|
|
32
|
+
<div className="flex w-full items-center justify-between text-xs sm:text-sm">
|
|
30
33
|
<div className="flex items-center gap-1 font-medium text-white opacity-60">
|
|
31
34
|
<CoinsIcon />
|
|
32
35
|
<div className="mr-1">Fees:</div>
|
|
33
36
|
{isGettingRoute ? (
|
|
34
|
-
<
|
|
37
|
+
<Skeleton width="w-20" height="h-4" />
|
|
35
38
|
) : (
|
|
36
39
|
` ${weiToHumanReadable({
|
|
37
40
|
amount: safeBigNumberFrom(
|
|
@@ -50,11 +53,15 @@ export const FeesDetails: FC<Props> = ({
|
|
|
50
53
|
<div className="flex gap-1 items-center">
|
|
51
54
|
<div
|
|
52
55
|
className={`flex gap-1 items-center font-medium ${
|
|
53
|
-
expressChecked
|
|
56
|
+
expressChecked && !exceedsExpressDeliveryLimit
|
|
57
|
+
? "text-x_green"
|
|
58
|
+
: "text-white opacity-60"
|
|
54
59
|
}`}
|
|
55
60
|
>
|
|
56
61
|
<TimerIcon />
|
|
57
|
-
{expressChecked
|
|
62
|
+
{expressChecked && !exceedsExpressDeliveryLimit
|
|
63
|
+
? "Fast ~ 30sec "
|
|
64
|
+
: "Normal ~ 30min"}
|
|
58
65
|
</div>
|
|
59
66
|
<div
|
|
60
67
|
onClick={() => setFeesDetailsShown((x) => !x)}
|
|
@@ -65,37 +72,44 @@ export const FeesDetails: FC<Props> = ({
|
|
|
65
72
|
</div>
|
|
66
73
|
</div>
|
|
67
74
|
{feesDetailsShown && (
|
|
68
|
-
<div className="flex w-full items-center justify-between ">
|
|
75
|
+
<div className="flex w-full items-center justify-between gap-2">
|
|
69
76
|
<div className="flex flex-col text-[10px] gap-1">
|
|
70
|
-
<div className="font-medium text-white opacity-60">
|
|
71
|
-
CCIP Fee
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
<div className="flex justify-between font-medium text-white opacity-60 gap-1">
|
|
78
|
+
<div>CCIP Fee:</div>
|
|
79
|
+
<div className="whitespace-nowrap">
|
|
80
|
+
{` ${weiToHumanReadable({
|
|
81
|
+
amount: route?.xSwapFees.ccipFee || "0",
|
|
82
|
+
decimals: 18,
|
|
83
|
+
precisionFractionalPlaces: 5,
|
|
84
|
+
})} ${paymentToken?.symbol}`}
|
|
85
|
+
</div>
|
|
77
86
|
</div>
|
|
78
|
-
<div className="font-medium text-white opacity-60">
|
|
79
|
-
Native Fee
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
87
|
+
<div className="flex justify-between font-medium text-white opacity-60 gap-1">
|
|
88
|
+
<div>Native Fee:</div>
|
|
89
|
+
<div className="whitespace-nowrap">
|
|
90
|
+
{` ${weiToHumanReadable({
|
|
91
|
+
amount: route?.xSwapFees.xSwapFee.nativeFee || "0",
|
|
92
|
+
decimals: 18,
|
|
93
|
+
precisionFractionalPlaces: 5,
|
|
94
|
+
})} ${paymentToken?.symbol}`}
|
|
95
|
+
</div>
|
|
85
96
|
</div>
|
|
86
97
|
</div>
|
|
87
98
|
<div className="flex flex-col text-[10px] gap-1">
|
|
88
|
-
<div className="font-medium text-white opacity-60">
|
|
89
|
-
Slippage
|
|
99
|
+
<div className="flex justify-between font-medium text-white opacity-60 gap-1">
|
|
100
|
+
<div>Slippage:</div>
|
|
101
|
+
<div className="whitespace-nowrap">{`${slippage}%`}</div>
|
|
90
102
|
</div>
|
|
91
|
-
<div className="font-medium text-white opacity-60">
|
|
92
|
-
Min amount out
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
103
|
+
<div className="flex justify-between font-medium text-white opacity-60 gap-1">
|
|
104
|
+
<div>Min amount out:</div>
|
|
105
|
+
<div className="whitespace-nowrap">
|
|
106
|
+
{weiToHumanReadable({
|
|
107
|
+
amount: route?.minAmountOut || "0",
|
|
108
|
+
decimals: dstToken?.decimals || 18,
|
|
109
|
+
precisionFractionalPlaces: 5,
|
|
110
|
+
})}{" "}
|
|
111
|
+
{dstToken?.symbol}
|
|
112
|
+
</div>
|
|
99
113
|
</div>
|
|
100
114
|
</div>
|
|
101
115
|
</div>
|
|
@@ -27,8 +27,10 @@ export const Form = ({
|
|
|
27
27
|
desc,
|
|
28
28
|
supportedChains,
|
|
29
29
|
onSubmit,
|
|
30
|
+
onClose,
|
|
30
31
|
}: TxConfigFormProps & {
|
|
31
32
|
onSubmit: (route: Route) => void;
|
|
33
|
+
onClose: () => void;
|
|
32
34
|
}) => {
|
|
33
35
|
const [signer, setSigner] = useState<string | undefined>();
|
|
34
36
|
const [dstChain, setDstChain] = useState<Chain>();
|
|
@@ -47,6 +49,8 @@ export const Form = ({
|
|
|
47
49
|
const [formError, setFormError] = useState("");
|
|
48
50
|
const [slippage, setSlippage] = useState<string>("1.5");
|
|
49
51
|
const [feesDetailsShown, setFeesDetailsShown] = useState(false);
|
|
52
|
+
const [exceedsExpressDeliveryLimit, setExceedsExpressDeliveryLimit] =
|
|
53
|
+
useState(false);
|
|
50
54
|
|
|
51
55
|
const debouncedAmount = useDebounce(amount, 1000);
|
|
52
56
|
const account = useAccount();
|
|
@@ -111,7 +115,7 @@ export const Form = ({
|
|
|
111
115
|
toToken: dstTokenAddr,
|
|
112
116
|
paymentToken: paymentToken.address,
|
|
113
117
|
slippage: Number(slippage),
|
|
114
|
-
expressDelivery: expressChecked,
|
|
118
|
+
expressDelivery: expressChecked && !exceedsExpressDeliveryLimit,
|
|
115
119
|
customContractCalls,
|
|
116
120
|
})
|
|
117
121
|
.then((response) => {
|
|
@@ -182,7 +186,7 @@ export const Form = ({
|
|
|
182
186
|
|
|
183
187
|
return (
|
|
184
188
|
<form
|
|
185
|
-
className="flex flex-col gap-2 z-10 my-0
|
|
189
|
+
className="flex flex-col gap-2 z-10 my-0 p-2 md:p-4 rounded-3xl overflow-hidden font-light sm:w-x_desktop"
|
|
186
190
|
onSubmit={handleSubmit}
|
|
187
191
|
>
|
|
188
192
|
<TopBar
|
|
@@ -190,6 +194,7 @@ export const Form = ({
|
|
|
190
194
|
historyTabShown={historyTabShown}
|
|
191
195
|
setHistoryTabShown={setHistoryTabShown}
|
|
192
196
|
setSettingsShown={setSettingsShown}
|
|
197
|
+
onClose={onClose}
|
|
193
198
|
/>
|
|
194
199
|
{settingsShown && (
|
|
195
200
|
<Settings
|
|
@@ -216,6 +221,7 @@ export const Form = ({
|
|
|
216
221
|
prices={prices}
|
|
217
222
|
supportedChains={supportedChains}
|
|
218
223
|
setSrcChain={setSrcChain}
|
|
224
|
+
setExceedsExpressDeliveryLimit={setExceedsExpressDeliveryLimit}
|
|
219
225
|
/>
|
|
220
226
|
<Summary
|
|
221
227
|
isGettingRoute={isGettingRoute}
|
|
@@ -229,6 +235,7 @@ export const Form = ({
|
|
|
229
235
|
paymentToken={paymentToken}
|
|
230
236
|
dstToken={dstToken}
|
|
231
237
|
expressChecked={expressChecked}
|
|
238
|
+
exceedsExpressDeliveryLimit={exceedsExpressDeliveryLimit}
|
|
232
239
|
slippage={slippage}
|
|
233
240
|
feesDetailsShown={feesDetailsShown}
|
|
234
241
|
setFeesDetailsShown={setFeesDetailsShown}
|
|
@@ -53,20 +53,24 @@ export const Summary: FC<Props> = ({
|
|
|
53
53
|
) : (
|
|
54
54
|
<div className="flex gap-2 items-center text-white text-xl sm:text-3xl">
|
|
55
55
|
{amountReadable}
|
|
56
|
-
<div className="w-4 sm:w-6 h-4 sm:h-6">
|
|
57
|
-
<img src={dstToken?.image} alt={dstToken?.name} />
|
|
58
|
-
</div>
|
|
59
|
-
<p className="text-base sm:text-xl">{dstToken?.symbol}</p>
|
|
60
56
|
</div>
|
|
61
57
|
)}
|
|
62
58
|
</div>
|
|
63
|
-
<div className="flex flex-col gap-1 text-sm">
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
59
|
+
<div className="flex flex-col items-end gap-1 text-sm">
|
|
60
|
+
<div className="flex justify-center items-center gap-1">
|
|
61
|
+
<div className="w-4 sm:w-6 h-4 sm:h-6">
|
|
62
|
+
<img src={dstToken?.image} alt={dstToken?.name} />
|
|
63
|
+
</div>
|
|
64
|
+
<p className="text-base sm:text-xl">{dstToken?.symbol}</p>
|
|
65
|
+
</div>
|
|
66
|
+
<div className="flex justify-center items-center gap-1">
|
|
67
|
+
<p className="text-[rgba(255,255,255,0.6)] text-right">on </p>
|
|
68
|
+
<div className="flex items-center gap-1 text-white">
|
|
69
|
+
<div className="w-4 h-4">
|
|
70
|
+
<img src={dstChain?.image} alt={dstChain?.name} />
|
|
71
|
+
</div>
|
|
72
|
+
<div>{dstChain?.displayName}</div>
|
|
68
73
|
</div>
|
|
69
|
-
<div>{dstChain?.displayName}</div>
|
|
70
74
|
</div>
|
|
71
75
|
</div>
|
|
72
76
|
</div>
|
|
@@ -75,6 +79,7 @@ export const Summary: FC<Props> = ({
|
|
|
75
79
|
token={dstToken}
|
|
76
80
|
amount={amountReadable}
|
|
77
81
|
loading={isGettingRoute}
|
|
82
|
+
type="dst"
|
|
78
83
|
/>
|
|
79
84
|
<div className="absolute right-[50%] top-0 translate-x-1/2 translate-y-[-60%] globalBorder rounded-xl p-[5px] bg-[rgba(15,15,15,1)]">
|
|
80
85
|
<div className=" flex items-center justify-center rounded-lg w-8 h-8 bg-gradient-to-l from-[rgba(54,129,198,1)] to-[rgba(43,74,157,1)] ">
|
|
@@ -19,6 +19,7 @@ interface Props {
|
|
|
19
19
|
balances: TokenBalances | undefined;
|
|
20
20
|
prices: TokenPrices | undefined;
|
|
21
21
|
supportedChains: Chain[];
|
|
22
|
+
setExceedsExpressDeliveryLimit: (exceeds: boolean) => void;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export const SwapPanel: FC<Props> = ({
|
|
@@ -32,6 +33,7 @@ export const SwapPanel: FC<Props> = ({
|
|
|
32
33
|
balances,
|
|
33
34
|
prices,
|
|
34
35
|
supportedChains,
|
|
36
|
+
setExceedsExpressDeliveryLimit,
|
|
35
37
|
}) => {
|
|
36
38
|
const [chainListShown, setChainListShown] = useState(false);
|
|
37
39
|
const [tokenListShown, setTokenListShown] = useState(false);
|
|
@@ -109,6 +111,8 @@ export const SwapPanel: FC<Props> = ({
|
|
|
109
111
|
token={srcToken}
|
|
110
112
|
amount={amount}
|
|
111
113
|
loading={false}
|
|
114
|
+
type="src"
|
|
115
|
+
setExceedsExpressDeliveryLimit={setExceedsExpressDeliveryLimit}
|
|
112
116
|
/>
|
|
113
117
|
</div>
|
|
114
118
|
</div>
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { FC } from "react";
|
|
2
2
|
import { shortAddress } from "@src/utils";
|
|
3
|
-
import { SettingsIcon, HistoryIcon } from "../icons";
|
|
3
|
+
import { SettingsIcon, HistoryIcon, CloseIcon } from "../icons";
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
6
6
|
signer: string | undefined;
|
|
7
7
|
setSettingsShown: React.Dispatch<React.SetStateAction<boolean>>;
|
|
8
8
|
historyTabShown: boolean;
|
|
9
9
|
setHistoryTabShown: React.Dispatch<React.SetStateAction<boolean>>;
|
|
10
|
+
onClose: () => void;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
export const TopBar: FC<Props> = ({
|
|
@@ -14,15 +15,16 @@ export const TopBar: FC<Props> = ({
|
|
|
14
15
|
setSettingsShown,
|
|
15
16
|
setHistoryTabShown,
|
|
16
17
|
historyTabShown,
|
|
18
|
+
onClose,
|
|
17
19
|
}) => {
|
|
18
20
|
return (
|
|
19
|
-
<div className="flex w-full justify-between items-center mx-auto
|
|
21
|
+
<div className="flex w-full justify-between items-center mx-auto p-2">
|
|
20
22
|
<div className="rounded-lg text-[rgba(255,255,255,0.6)] text-xs sm:text-base whitespace-nowrap">
|
|
21
23
|
{signer
|
|
22
24
|
? `Connected wallet: ${shortAddress(signer)}`
|
|
23
25
|
: `Wallet disconnected`}
|
|
24
26
|
</div>
|
|
25
|
-
<div className="flex gap-2">
|
|
27
|
+
<div className="flex gap-2 justify-center items-center">
|
|
26
28
|
{!historyTabShown && (
|
|
27
29
|
<div
|
|
28
30
|
onClick={() => setSettingsShown(true)}
|
|
@@ -47,6 +49,9 @@ export const TopBar: FC<Props> = ({
|
|
|
47
49
|
<div>Back</div>
|
|
48
50
|
)}
|
|
49
51
|
</div>
|
|
52
|
+
<div className="cursor-pointer text-white" onClick={onClose}>
|
|
53
|
+
<CloseIcon />
|
|
54
|
+
</div>
|
|
50
55
|
</div>
|
|
51
56
|
</div>
|
|
52
57
|
);
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { Alert, Skeleton } from "@src/components";
|
|
2
2
|
import { Token, TokenPrices } from "@src/models";
|
|
3
3
|
import { FC, useEffect, useMemo, useState } from "react";
|
|
4
|
+
import { EXPRESS_DELIVERY_LIMIT } from "@src/constants";
|
|
4
5
|
|
|
5
6
|
type Props = {
|
|
6
7
|
prices: TokenPrices | undefined;
|
|
7
8
|
token: Token | undefined;
|
|
8
9
|
amount: string | undefined;
|
|
9
10
|
loading: boolean;
|
|
11
|
+
type: "src" | "dst";
|
|
12
|
+
setExceedsExpressDeliveryLimit?: (exceeds: boolean) => void;
|
|
10
13
|
};
|
|
11
14
|
|
|
12
15
|
export const UsdPrice: FC<Props> = ({
|
|
@@ -14,12 +17,22 @@ export const UsdPrice: FC<Props> = ({
|
|
|
14
17
|
token,
|
|
15
18
|
amount = "0",
|
|
16
19
|
loading = false,
|
|
20
|
+
type,
|
|
21
|
+
setExceedsExpressDeliveryLimit,
|
|
17
22
|
}) => {
|
|
18
23
|
const [usdPrice, setUsdPrice] = useState<string>("0.00");
|
|
19
24
|
|
|
20
25
|
useEffect(() => {
|
|
21
26
|
if (token && prices && prices[token.address]) {
|
|
22
|
-
|
|
27
|
+
const newUsdPrice = (
|
|
28
|
+
Number(amount) * Number(prices[token.address])
|
|
29
|
+
).toFixed(2);
|
|
30
|
+
if (type === "src" && setExceedsExpressDeliveryLimit) {
|
|
31
|
+
setExceedsExpressDeliveryLimit(
|
|
32
|
+
Number(newUsdPrice) > EXPRESS_DELIVERY_LIMIT,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
setUsdPrice(newUsdPrice);
|
|
23
36
|
}
|
|
24
37
|
}, [token, prices, amount]);
|
|
25
38
|
|
|
@@ -2,9 +2,8 @@ import "@src/global.css";
|
|
|
2
2
|
import { MouseEvent, useMemo } from "react";
|
|
3
3
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
4
4
|
import { WagmiProvider } from "wagmi";
|
|
5
|
-
import { getWagmiConfig, xswapRoot } from "@src/config";
|
|
5
|
+
import { getWagmiConfig, waitForInitialization, xswapRoot } from "@src/config";
|
|
6
6
|
import { Chain, ContractCall, Route } from "@src/models";
|
|
7
|
-
import { CloseIcon } from "@src/components/icons/CloseIcon";
|
|
8
7
|
import { PoweredBy } from "@src/components/TxConfigForm/PoweredBy";
|
|
9
8
|
import { Form } from "./Form";
|
|
10
9
|
|
|
@@ -49,7 +48,7 @@ const TxConfigForm = ({
|
|
|
49
48
|
className="top-0 left-0 right-0 bottom-0 bg-[rgba(0,0,0,0.8)] fixed flex items-center justify-center z-10"
|
|
50
49
|
onClick={onBackdropClick}
|
|
51
50
|
>
|
|
52
|
-
<div className="relative bg-black rounded-3xl
|
|
51
|
+
<div className="relative bg-black rounded-3xl overflow-auto text-white border-2 border-solid border-[rgba(255,255,255,0.1)]">
|
|
53
52
|
<Form
|
|
54
53
|
dstChainId={dstChainId}
|
|
55
54
|
dstTokenAddr={dstTokenAddr}
|
|
@@ -57,13 +56,8 @@ const TxConfigForm = ({
|
|
|
57
56
|
desc={desc}
|
|
58
57
|
supportedChains={supportedChains}
|
|
59
58
|
onSubmit={onSubmit}
|
|
59
|
+
onClose={onClose}
|
|
60
60
|
/>
|
|
61
|
-
<div
|
|
62
|
-
className="absolute top-7 right-4 cursor-pointer text-white"
|
|
63
|
-
onClick={onClose}
|
|
64
|
-
>
|
|
65
|
-
<CloseIcon />
|
|
66
|
-
</div>
|
|
67
61
|
<PoweredBy />
|
|
68
62
|
</div>
|
|
69
63
|
</div>
|
|
@@ -80,7 +74,8 @@ export const openTxConfigForm = async ({
|
|
|
80
74
|
supportedChains,
|
|
81
75
|
}: TxConfigFormProps): Promise<Route> => {
|
|
82
76
|
try {
|
|
83
|
-
return await new Promise((resolve) => {
|
|
77
|
+
return await new Promise(async (resolve) => {
|
|
78
|
+
await waitForInitialization();
|
|
84
79
|
xswapRoot.render(
|
|
85
80
|
<TxConfigForm
|
|
86
81
|
dstChainId={dstChainId}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const WaitingForInit = () => {
|
|
2
|
+
return (
|
|
3
|
+
<div
|
|
4
|
+
style={{
|
|
5
|
+
zIndex: 10,
|
|
6
|
+
top: 0,
|
|
7
|
+
right: 0,
|
|
8
|
+
bottom: 0,
|
|
9
|
+
left: 0,
|
|
10
|
+
backgroundColor: "rgba(0,0,0,0.8)",
|
|
11
|
+
position: "fixed",
|
|
12
|
+
display: "flex",
|
|
13
|
+
alignItems: "center",
|
|
14
|
+
justifyContent: "center",
|
|
15
|
+
}}
|
|
16
|
+
>
|
|
17
|
+
Waiting for XPay initialization ...
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createRoot, Root } from "react-dom/client";
|
|
2
|
+
import xswapConfig from "../../xswap.config";
|
|
3
|
+
import { version } from "../../package.json";
|
|
4
|
+
import { WaitingForInit } from "@src/components/WaitingForInit";
|
|
5
|
+
|
|
6
|
+
export let initIndicatorRoot: Root;
|
|
7
|
+
export let xswapRoot: Root;
|
|
8
|
+
export let txStatusRoot: Root;
|
|
9
|
+
|
|
10
|
+
let initCompleted = false;
|
|
11
|
+
|
|
12
|
+
export const initDocument = () => {
|
|
13
|
+
if (typeof document === "undefined") {
|
|
14
|
+
throw new Error("Can't render XPay components from server side.");
|
|
15
|
+
}
|
|
16
|
+
createInitIndicatorRoot();
|
|
17
|
+
|
|
18
|
+
Promise.all([
|
|
19
|
+
createStyleElement(),
|
|
20
|
+
createXswapRoot(),
|
|
21
|
+
createTxStatusRoot(),
|
|
22
|
+
]).then(() => {
|
|
23
|
+
initCompleted = true;
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const waitForInitialization = async () => {
|
|
28
|
+
if (!initCompleted) {
|
|
29
|
+
displayInitIndicator(true);
|
|
30
|
+
while (!initCompleted) {
|
|
31
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
32
|
+
}
|
|
33
|
+
displayInitIndicator(false);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const createStyleElement = async () => {
|
|
38
|
+
const css = await fetch(
|
|
39
|
+
`${xswapConfig.apiUrl}/sdk/css?${new URLSearchParams({
|
|
40
|
+
data: JSON.stringify({ version }),
|
|
41
|
+
})}`,
|
|
42
|
+
);
|
|
43
|
+
const text = await css.text();
|
|
44
|
+
const style = document.createElement("style");
|
|
45
|
+
style.textContent = text;
|
|
46
|
+
document.body.appendChild(style);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const createXswapRoot = async () => {
|
|
50
|
+
const xswapElement = document.createElement("div");
|
|
51
|
+
xswapElement.setAttribute("id", "xswap-modal");
|
|
52
|
+
document.body.appendChild(xswapElement);
|
|
53
|
+
xswapRoot = createRoot(xswapElement);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const createTxStatusRoot = async () => {
|
|
57
|
+
const txStatusElement = document.createElement("div");
|
|
58
|
+
txStatusElement.setAttribute("id", "xswap-tx-status");
|
|
59
|
+
txStatusElement.setAttribute("class", "xswap-tx-status");
|
|
60
|
+
document.body.appendChild(txStatusElement);
|
|
61
|
+
txStatusRoot = createRoot(txStatusElement);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const createInitIndicatorRoot = () => {
|
|
65
|
+
const initIndicatorElement = document.createElement("div");
|
|
66
|
+
initIndicatorElement.setAttribute("id", "xswap-init-indicator");
|
|
67
|
+
document.body.appendChild(initIndicatorElement);
|
|
68
|
+
initIndicatorRoot = createRoot(initIndicatorElement);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const displayInitIndicator = (display: boolean) => {
|
|
72
|
+
display
|
|
73
|
+
? initIndicatorRoot.render(<WaitingForInit />)
|
|
74
|
+
: initIndicatorRoot.render("");
|
|
75
|
+
};
|
package/src/constants/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ export const NUMBER_INPUT_REGEX = /^[0-9]*[.,]?[0-9]*$/;
|
|
|
5
5
|
export const SLIPPAGE_PRESETS: number[] = [0.5, 1.5, 3.0];
|
|
6
6
|
export const DELIVERY_TIME = 30 * 1000 * 60;
|
|
7
7
|
export const EXPRESS_DELIVERY_TIME = 30 * 1000;
|
|
8
|
+
export const EXPRESS_DELIVERY_LIMIT = 1000; // USD
|
|
8
9
|
export const BALANCES_CHUNK_SIZE = 500;
|
|
9
10
|
export const ROUTE_TIMEOUT_MS = 5000;
|
|
10
11
|
export const MINIMUM_DISPLAYED_TOKEN_AMOUNT = 0.0001;
|
package/src/models/Route.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { TransactionRequest } from "@ethersproject/providers";
|
|
2
|
-
|
|
3
1
|
export type Route = {
|
|
4
2
|
estAmountOut: string;
|
|
5
3
|
minAmountOut: string;
|
|
@@ -13,6 +11,12 @@ export type Transactions = {
|
|
|
13
11
|
swap: TransactionRequest;
|
|
14
12
|
};
|
|
15
13
|
|
|
14
|
+
export type TransactionRequest = {
|
|
15
|
+
to: string;
|
|
16
|
+
data: string;
|
|
17
|
+
value: string;
|
|
18
|
+
};
|
|
19
|
+
|
|
16
20
|
export type XSwapFees = {
|
|
17
21
|
ccipFee?: string;
|
|
18
22
|
xSwapFee: XSwapFee;
|
package/src/utils/contracts.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { BigNumber, BigNumberish, ethers } from "ethers";
|
|
2
|
-
import { TransactionRequest } from "@ethersproject/providers";
|
|
3
|
-
import { safeBigNumberFrom } from "./numbers";
|
|
4
2
|
import { ADDRESSES, BatchQueryAbi, ERC20Abi } from "@src/contracts";
|
|
5
|
-
import { Chain, TokenBalances } from "@src/models";
|
|
3
|
+
import { Chain, TokenBalances, TransactionRequest } from "@src/models";
|
|
6
4
|
import { chunkArray } from "@src/utils";
|
|
7
5
|
import { BALANCES_CHUNK_SIZE } from "@src/constants";
|
|
8
6
|
|
|
@@ -104,7 +102,7 @@ export const generateApproveTxData = (
|
|
|
104
102
|
return tokenAddress !== ethers.constants.AddressZero
|
|
105
103
|
? {
|
|
106
104
|
to: tokenAddress,
|
|
107
|
-
value:
|
|
105
|
+
value: "0",
|
|
108
106
|
data: IERC20.encodeFunctionData("approve", [spender, amount]),
|
|
109
107
|
}
|
|
110
108
|
: undefined;
|
package/tailwind.config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** @type {import("tailwindcss").Config} */
|
|
2
|
-
|
|
2
|
+
export default {
|
|
3
3
|
content: ["./src/components/**/*.{js,ts,jsx,tsx,mdx}"],
|
|
4
4
|
theme: {
|
|
5
5
|
extend: {
|
|
@@ -18,7 +18,7 @@ module.exports = {
|
|
|
18
18
|
},
|
|
19
19
|
width: {
|
|
20
20
|
x_desktop: "600px",
|
|
21
|
-
x_mobile: "
|
|
21
|
+
x_mobile: "360px",
|
|
22
22
|
},
|
|
23
23
|
animation: {
|
|
24
24
|
"spin-slow": "spin 3s linear infinite",
|
package/src/config/init.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { createRoot, Root } from "react-dom/client";
|
|
2
|
-
import xswapConfig from "../../xswap.config";
|
|
3
|
-
import { version } from "../../package.json";
|
|
4
|
-
|
|
5
|
-
export let xswapRoot: Root;
|
|
6
|
-
export let txStatusRoot: Root;
|
|
7
|
-
|
|
8
|
-
export const initDocument = () => {
|
|
9
|
-
if (typeof document === "undefined") {
|
|
10
|
-
throw new Error("Can't render XPay components from server side.");
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
fetch(`${xswapConfig.apiUrl}/sdk/css?data={"version": "${version}"}`).then(
|
|
14
|
-
async (css) => {
|
|
15
|
-
const style = document.createElement("style");
|
|
16
|
-
style.textContent = await css.text();
|
|
17
|
-
document.body.appendChild(style);
|
|
18
|
-
},
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
const xswapElement = document.createElement("div");
|
|
22
|
-
xswapElement.setAttribute("id", "xswap-modal");
|
|
23
|
-
document.body.appendChild(xswapElement);
|
|
24
|
-
xswapRoot = createRoot(xswapElement);
|
|
25
|
-
|
|
26
|
-
const txStatusElement = document.createElement("div");
|
|
27
|
-
txStatusElement.setAttribute("id", "xswap-tx-status");
|
|
28
|
-
txStatusElement.setAttribute("class", "xswap-tx-status");
|
|
29
|
-
document.body.appendChild(txStatusElement);
|
|
30
|
-
txStatusRoot = createRoot(txStatusElement);
|
|
31
|
-
};
|