@xswap-link/sdk 0.2.3 → 0.2.5

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.
Files changed (36) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/index.css +20 -21
  3. package/dist/index.d.mts +24 -13
  4. package/dist/index.d.ts +24 -13
  5. package/dist/index.js +747 -527
  6. package/dist/index.mjs +645 -425
  7. package/package.json +1 -1
  8. package/src/components/TxConfigForm/FeesDetails.tsx +55 -37
  9. package/src/components/TxConfigForm/Form.tsx +30 -7
  10. package/src/components/TxConfigForm/History.tsx +31 -4
  11. package/src/components/TxConfigForm/Summary.tsx +28 -11
  12. package/src/components/TxConfigForm/SwapPanel.tsx +5 -1
  13. package/src/components/TxConfigForm/TopBar.tsx +8 -3
  14. package/src/components/TxConfigForm/UsdPrice.tsx +14 -1
  15. package/src/components/TxConfigForm/index.tsx +10 -10
  16. package/src/components/TxStatusButton/index.tsx +21 -13
  17. package/src/components/UnknownTokenLogo/UnknownTokenLogo.tsx +14 -0
  18. package/src/components/WaitingForInit/index.tsx +20 -0
  19. package/src/components/global.css +1 -1
  20. package/src/config/init.tsx +75 -0
  21. package/src/constants/index.ts +1 -0
  22. package/src/index.ts +9 -1
  23. package/src/models/Route.ts +6 -2
  24. package/src/models/TokenData.ts +1 -1
  25. package/src/models/TransactionHistory.ts +12 -8
  26. package/src/models/payloads/GetRoutePayload.ts +1 -0
  27. package/src/models/payloads/GetSwapTxPayload.ts +1 -0
  28. package/src/services/api.ts +9 -0
  29. package/src/services/blockchain.ts +49 -0
  30. package/src/services/index.ts +1 -0
  31. package/src/services/integrations/monitoring.ts +34 -14
  32. package/src/services/integrations/transactions.ts +8 -3
  33. package/src/utils/contracts.ts +2 -4
  34. package/src/utils/strings.ts +4 -0
  35. package/tailwind.config.js +2 -2
  36. package/src/config/init.ts +0 -35
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xswap-link/sdk",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "JavaScript SDK for XSwap platform",
5
5
  "homepage": "https://github.com/xswap-link/xswap-sdk",
6
6
  "repository": {
@@ -1,7 +1,8 @@
1
- import { FC } from "react";
1
+ import { FC, useMemo } 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,23 @@ 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
  }) => {
30
+ const isExpressDeliveryPossible = useMemo(() => {
31
+ return expressChecked && !exceedsExpressDeliveryLimit;
32
+ }, [expressChecked, exceedsExpressDeliveryLimit]);
33
+
27
34
  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 ">
35
+ <div className="flex flex-col gap-3 globalBorder rounded-lg bg-[rgba(15,15,15,1)] p-2 sm:p-4 mb-1">
36
+ <div className="flex w-full items-center justify-between text-xs sm:text-sm">
30
37
  <div className="flex items-center gap-1 font-medium text-white opacity-60">
31
38
  <CoinsIcon />
32
39
  <div className="mr-1">Fees:</div>
33
40
  {isGettingRoute ? (
34
- <div className="bg-current rounded animate-pulse w-20 h-4" />
41
+ <Skeleton width="w-20" height="h-4" />
35
42
  ) : (
36
43
  ` ${weiToHumanReadable({
37
44
  amount: safeBigNumberFrom(
@@ -48,14 +55,18 @@ export const FeesDetails: FC<Props> = ({
48
55
  )}
49
56
  </div>
50
57
  <div className="flex gap-1 items-center">
51
- <div
52
- className={`flex gap-1 items-center font-medium ${
53
- expressChecked ? "text-x_green" : "text-white opacity-60"
54
- }`}
55
- >
56
- <TimerIcon />
57
- {expressChecked ? "Fast ~ 30sec " : "Normal ~ 30min"}
58
- </div>
58
+ {route?.xSwapFees.expressDeliveryFee && !isGettingRoute && (
59
+ <div
60
+ className={`flex gap-1 items-center font-medium ${
61
+ isExpressDeliveryPossible
62
+ ? "text-x_green"
63
+ : "text-white opacity-60"
64
+ }`}
65
+ >
66
+ <TimerIcon />
67
+ {isExpressDeliveryPossible ? "Fast ~ 30sec " : "Normal ~ 30min"}
68
+ </div>
69
+ )}
59
70
  <div
60
71
  onClick={() => setFeesDetailsShown((x) => !x)}
61
72
  className="font-medium text-white opacity-60 cursor-pointer flex items-center w-[15px] h-[9px]"
@@ -65,37 +76,44 @@ export const FeesDetails: FC<Props> = ({
65
76
  </div>
66
77
  </div>
67
78
  {feesDetailsShown && (
68
- <div className="flex w-full items-center justify-between ">
79
+ <div className="flex w-full items-center justify-between gap-2">
69
80
  <div className="flex flex-col text-[10px] gap-1">
70
- <div className="font-medium text-white opacity-60">
71
- CCIP Fee:
72
- {` ${weiToHumanReadable({
73
- amount: route?.xSwapFees.ccipFee || "0",
74
- decimals: 18,
75
- precisionFractionalPlaces: 5,
76
- })} ${paymentToken?.symbol}`}
81
+ <div className="flex justify-between font-medium text-white opacity-60 gap-1">
82
+ <div>CCIP Fee:</div>
83
+ <div className="whitespace-nowrap">
84
+ {` ${weiToHumanReadable({
85
+ amount: route?.xSwapFees.ccipFee || "0",
86
+ decimals: 18,
87
+ precisionFractionalPlaces: 5,
88
+ })} ${paymentToken?.symbol}`}
89
+ </div>
77
90
  </div>
78
- <div className="font-medium text-white opacity-60">
79
- Native Fee:
80
- {` ${weiToHumanReadable({
81
- amount: route?.xSwapFees.xSwapFee.nativeFee || "0",
82
- decimals: 18,
83
- precisionFractionalPlaces: 5,
84
- })} ${paymentToken?.symbol}`}
91
+ <div className="flex justify-between font-medium text-white opacity-60 gap-1">
92
+ <div>Native Fee:</div>
93
+ <div className="whitespace-nowrap">
94
+ {` ${weiToHumanReadable({
95
+ amount: route?.xSwapFees.xSwapFee.nativeFee || "0",
96
+ decimals: 18,
97
+ precisionFractionalPlaces: 5,
98
+ })} ${paymentToken?.symbol}`}
99
+ </div>
85
100
  </div>
86
101
  </div>
87
102
  <div className="flex flex-col text-[10px] gap-1">
88
- <div className="font-medium text-white opacity-60">
89
- Slippage: {`${slippage}%`}
103
+ <div className="flex justify-between font-medium text-white opacity-60 gap-1">
104
+ <div>Slippage:</div>
105
+ <div className="whitespace-nowrap">{`${slippage}%`}</div>
90
106
  </div>
91
- <div className="font-medium text-white opacity-60">
92
- Min amount out:{" "}
93
- {weiToHumanReadable({
94
- amount: route?.minAmountOut || "0",
95
- decimals: dstToken?.decimals || 18,
96
- precisionFractionalPlaces: 5,
97
- })}{" "}
98
- {dstToken?.symbol}
107
+ <div className="flex justify-between font-medium text-white opacity-60 gap-1">
108
+ <div>Min amount out:</div>
109
+ <div className="whitespace-nowrap">
110
+ {weiToHumanReadable({
111
+ amount: route?.minAmountOut || "0",
112
+ decimals: dstToken?.decimals || 18,
113
+ precisionFractionalPlaces: 5,
114
+ })}{" "}
115
+ {dstToken?.symbol}
116
+ </div>
99
117
  </div>
100
118
  </div>
101
119
  </div>
@@ -3,7 +3,7 @@ import React, { FormEvent, useEffect, useState } from "react";
3
3
  import { ethers } from "ethers";
4
4
  import { useAccount, useSwitchChain } from "wagmi";
5
5
  import { Chain, Route, Token, TokenBalances, TokenPrices } from "@src/models";
6
- import { getPrices, getRoute } from "@src/services";
6
+ import { getCustomTokenData, getPrices, getRoute } from "@src/services";
7
7
  import { getBalances } from "@src/utils";
8
8
  import { ROUTE_TIMEOUT_MS } from "@src/constants";
9
9
  import { TxConfigFormProps } from "@src/components";
@@ -21,14 +21,17 @@ import { DEFAULT_SOURCE_CHAIN_ID } from "@src/constants";
21
21
  import { Button } from "./Button";
22
22
 
23
23
  export const Form = ({
24
+ integratorId,
24
25
  dstChainId,
25
26
  dstTokenAddr,
26
27
  customContractCalls,
27
28
  desc,
28
29
  supportedChains,
29
30
  onSubmit,
31
+ onClose,
30
32
  }: TxConfigFormProps & {
31
33
  onSubmit: (route: Route) => void;
34
+ onClose: () => void;
32
35
  }) => {
33
36
  const [signer, setSigner] = useState<string | undefined>();
34
37
  const [dstChain, setDstChain] = useState<Chain>();
@@ -47,6 +50,8 @@ export const Form = ({
47
50
  const [formError, setFormError] = useState("");
48
51
  const [slippage, setSlippage] = useState<string>("1.5");
49
52
  const [feesDetailsShown, setFeesDetailsShown] = useState(false);
53
+ const [exceedsExpressDeliveryLimit, setExceedsExpressDeliveryLimit] =
54
+ useState(false);
50
55
 
51
56
  const debouncedAmount = useDebounce(amount, 1000);
52
57
  const account = useAccount();
@@ -73,15 +78,29 @@ export const Form = ({
73
78
  }, [supportedChains, dstChainId]);
74
79
 
75
80
  useEffect(() => {
76
- setDstToken(
77
- dstChain?.tokens.find(
81
+ (async () => {
82
+ if (!dstChain) {
83
+ return;
84
+ }
85
+
86
+ let dstTokenResult = dstChain?.tokens.find(
78
87
  (token) => token.address.toLowerCase() === dstTokenAddr.toLowerCase(),
79
- ),
80
- );
88
+ );
89
+
90
+ if (!dstTokenResult) {
91
+ dstTokenResult = await getCustomTokenData(
92
+ dstChain,
93
+ dstTokenAddr.toLowerCase(),
94
+ );
95
+ }
96
+
97
+ setDstToken(dstTokenResult);
98
+ })();
81
99
  }, [dstChain]);
82
100
 
83
101
  useEffect(() => {
84
102
  if (
103
+ integratorId &&
85
104
  srcChain &&
86
105
  srcToken &&
87
106
  dstChain &&
@@ -100,6 +119,7 @@ export const Form = ({
100
119
  `Configuration error: selected token ($${srcToken.symbol} ${srcToken.name}) has unknown decimals param.`,
101
120
  );
102
121
  getRoute({
122
+ integratorId,
103
123
  fromAmount: ethers.utils
104
124
  .parseUnits(debouncedAmount, srcToken.decimals)
105
125
  .toString(),
@@ -111,7 +131,7 @@ export const Form = ({
111
131
  toToken: dstTokenAddr,
112
132
  paymentToken: paymentToken.address,
113
133
  slippage: Number(slippage),
114
- expressDelivery: expressChecked,
134
+ expressDelivery: expressChecked && !exceedsExpressDeliveryLimit,
115
135
  customContractCalls,
116
136
  })
117
137
  .then((response) => {
@@ -182,7 +202,7 @@ export const Form = ({
182
202
 
183
203
  return (
184
204
  <form
185
- className="flex flex-col gap-2 z-10 my-0 mx-auto p-4 rounded-3xl overflow-hidden font-light w-x_mobile sm:w-x_desktop"
205
+ 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
206
  onSubmit={handleSubmit}
187
207
  >
188
208
  <TopBar
@@ -190,6 +210,7 @@ export const Form = ({
190
210
  historyTabShown={historyTabShown}
191
211
  setHistoryTabShown={setHistoryTabShown}
192
212
  setSettingsShown={setSettingsShown}
213
+ onClose={onClose}
193
214
  />
194
215
  {settingsShown && (
195
216
  <Settings
@@ -216,6 +237,7 @@ export const Form = ({
216
237
  prices={prices}
217
238
  supportedChains={supportedChains}
218
239
  setSrcChain={setSrcChain}
240
+ setExceedsExpressDeliveryLimit={setExceedsExpressDeliveryLimit}
219
241
  />
220
242
  <Summary
221
243
  isGettingRoute={isGettingRoute}
@@ -229,6 +251,7 @@ export const Form = ({
229
251
  paymentToken={paymentToken}
230
252
  dstToken={dstToken}
231
253
  expressChecked={expressChecked}
254
+ exceedsExpressDeliveryLimit={exceedsExpressDeliveryLimit}
232
255
  slippage={slippage}
233
256
  feesDetailsShown={feesDetailsShown}
234
257
  setFeesDetailsShown={setFeesDetailsShown}
@@ -21,15 +21,42 @@ export const History: FC<Props> = ({ signer, supportedChains }) => {
21
21
  const fetchedTransactions: Transaction[] = [];
22
22
  if (downloadedHistory) {
23
23
  for (const entry of downloadedHistory.history) {
24
+ let status: TransactionStatus = "IN_PROGRESS";
25
+
26
+ // single chain tx
24
27
  if (!entry.source) {
25
28
  continue;
26
29
  }
27
- let status: TransactionStatus;
28
- if (entry.failed) status = "REVERTED";
30
+
31
+ if (entry.failed) {
32
+ status = "REVERTED";
33
+ }
29
34
  if (!!entry.target) {
30
35
  status = "DONE";
31
- } else {
32
- status = "IN_PROGRESS";
36
+ }
37
+
38
+ if (entry.transferType === "SINGLE_CHAIN") {
39
+ if (!entry.target) {
40
+ continue;
41
+ }
42
+
43
+ const blockTimestampMs = new Date(entry.target.blockTime).getTime();
44
+ const estimatedDeliveryTimestamp = blockTimestampMs / 1000;
45
+
46
+ fetchedTransactions.push({
47
+ hash: entry.target.transactionHash,
48
+ timestamp: blockTimestampMs / 1000,
49
+ sourceChainId: entry.target.blockchainId,
50
+ targetChainId: entry.target.blockchainId,
51
+ amountWei: entry.source.tokenAmount,
52
+ tokenAddress: entry.source.tokenAddress,
53
+ tokenOutAddress: entry.target?.tokenAmount,
54
+ tokenOutAmount: entry.target?.tokenAmount,
55
+ estimatedDeliveryTimestamp,
56
+ status,
57
+ });
58
+
59
+ continue;
33
60
  }
34
61
 
35
62
  const blockTimestampMs = new Date(entry.source.blockTime).getTime();
@@ -1,10 +1,11 @@
1
- import React, { FC, useEffect, useMemo, useState } from "react";
1
+ import { FC, useEffect, useMemo, useState } from "react";
2
2
  import { weiToHumanReadable } from "@src/utils";
3
3
  import { Chain, Route, Token, TokenPrices } from "@src/models";
4
4
  import { ArrowDownIcon } from "../icons";
5
5
  import { UsdPrice } from "@src/components/TxConfigForm/UsdPrice";
6
6
  import { getPrices } from "@src/services";
7
7
  import { Skeleton } from "@src/components";
8
+ import { UnknownTokenLogo } from "../UnknownTokenLogo/UnknownTokenLogo";
8
9
 
9
10
  interface Props {
10
11
  isGettingRoute: boolean;
@@ -53,20 +54,35 @@ export const Summary: FC<Props> = ({
53
54
  ) : (
54
55
  <div className="flex gap-2 items-center text-white text-xl sm:text-3xl">
55
56
  {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
57
  </div>
61
58
  )}
62
59
  </div>
63
- <div className="flex flex-col gap-1 text-sm">
64
- <p className="text-[rgba(255,255,255,0.6)] text-right">on chain:</p>
65
- <div className="flex items-center gap-1 text-white">
66
- <div className="w-4 h-4">
67
- <img src={dstChain?.image} alt={dstChain?.name} />
60
+ <div className="flex flex-col items-end gap-1 text-sm">
61
+ <div className="flex justify-center items-center gap-1">
62
+ <div className="w-5 h-5">
63
+ {dstToken?.image ? (
64
+ <img
65
+ className="w-5 h-5"
66
+ src={dstToken?.image}
67
+ alt={dstToken?.name}
68
+ />
69
+ ) : (
70
+ <UnknownTokenLogo
71
+ tokenName={"?"}
72
+ className="token-select__generated-logo"
73
+ />
74
+ )}
75
+ </div>
76
+ <p className="text-base sm:text-xl">{dstToken?.name}</p>
77
+ </div>
78
+ <div className="flex justify-center items-center gap-1">
79
+ <p className="text-[rgba(255,255,255,0.6)] text-right">on </p>
80
+ <div className="flex items-center gap-1 text-white">
81
+ <div className="w-4 h-4">
82
+ <img src={dstChain?.image} alt={dstChain?.name} />
83
+ </div>
84
+ <div>{dstChain?.displayName}</div>
68
85
  </div>
69
- <div>{dstChain?.displayName}</div>
70
86
  </div>
71
87
  </div>
72
88
  </div>
@@ -75,6 +91,7 @@ export const Summary: FC<Props> = ({
75
91
  token={dstToken}
76
92
  amount={amountReadable}
77
93
  loading={isGettingRoute}
94
+ type="dst"
78
95
  />
79
96
  <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
97
  <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);
@@ -61,7 +63,7 @@ export const SwapPanel: FC<Props> = ({
61
63
  weiToHumanReadable({
62
64
  amount: balances[srcToken.address]?.toString() || "0",
63
65
  decimals: srcToken.decimals,
64
- precisionFractionalPlaces: 4,
66
+ precisionFractionalPlaces: srcToken.decimals,
65
67
  }),
66
68
  );
67
69
  };
@@ -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 sm:pl-4 pr-8 pt-2">
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
- setUsdPrice((Number(amount) * Number(prices[token.address])).toFixed(2));
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,13 +2,13 @@ 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
 
11
10
  export type TxConfigFormProps = {
11
+ integratorId: string;
12
12
  dstChainId: string;
13
13
  dstTokenAddr: string;
14
14
  customContractCalls: ContractCall[];
@@ -17,6 +17,7 @@ export type TxConfigFormProps = {
17
17
  };
18
18
 
19
19
  const TxConfigForm = ({
20
+ integratorId,
20
21
  dstChainId,
21
22
  dstTokenAddr,
22
23
  customContractCalls,
@@ -49,21 +50,17 @@ const TxConfigForm = ({
49
50
  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
51
  onClick={onBackdropClick}
51
52
  >
52
- <div className="relative bg-black rounded-3xl w-lg overflow-auto text-white border-2 border-solid border-[rgba(255,255,255,0.1)]">
53
+ <div className="relative bg-black rounded-3xl overflow-auto text-white border-2 border-solid border-[rgba(255,255,255,0.1)]">
53
54
  <Form
55
+ integratorId={integratorId}
54
56
  dstChainId={dstChainId}
55
57
  dstTokenAddr={dstTokenAddr}
56
58
  customContractCalls={customContractCalls}
57
59
  desc={desc}
58
60
  supportedChains={supportedChains}
59
61
  onSubmit={onSubmit}
62
+ onClose={onClose}
60
63
  />
61
- <div
62
- className="absolute top-7 right-4 cursor-pointer text-white"
63
- onClick={onClose}
64
- >
65
- <CloseIcon />
66
- </div>
67
64
  <PoweredBy />
68
65
  </div>
69
66
  </div>
@@ -73,6 +70,7 @@ const TxConfigForm = ({
73
70
  };
74
71
 
75
72
  export const openTxConfigForm = async ({
73
+ integratorId,
76
74
  dstChainId,
77
75
  dstTokenAddr,
78
76
  customContractCalls,
@@ -80,9 +78,11 @@ export const openTxConfigForm = async ({
80
78
  supportedChains,
81
79
  }: TxConfigFormProps): Promise<Route> => {
82
80
  try {
83
- return await new Promise((resolve) => {
81
+ return await new Promise(async (resolve) => {
82
+ await waitForInitialization();
84
83
  xswapRoot.render(
85
84
  <TxConfigForm
85
+ integratorId={integratorId}
86
86
  dstChainId={dstChainId}
87
87
  dstTokenAddr={dstTokenAddr}
88
88
  customContractCalls={customContractCalls}
@@ -9,6 +9,7 @@ import {
9
9
  } from "../icons";
10
10
  import { MonitoredTransaction } from "@src/models";
11
11
  import { txStatusRoot } from "@src/config";
12
+ import { UnknownTokenLogo } from "../UnknownTokenLogo/UnknownTokenLogo";
12
13
 
13
14
  interface Props {
14
15
  transaction: MonitoredTransaction;
@@ -16,15 +17,14 @@ interface Props {
16
17
 
17
18
  export const TxStatusButton: FC<Props> = ({ transaction }) => {
18
19
  const {
19
- fromChain,
20
- fromChainImage,
21
- fromToken,
22
- fromTokenImage,
23
- fromAmount,
24
- toChain,
25
- toChainImage,
20
+ srcChain: fromChain,
21
+ srcChainImage: fromChainImage,
22
+ srcToken: fromToken,
23
+ srcTokenImage: fromTokenImage,
24
+ srcAmount: fromAmount,
25
+ dstChain: toChain,
26
+ dstChainImage: toChainImage,
26
27
  isDone,
27
- txHash,
28
28
  explorer,
29
29
  } = transaction;
30
30
  const [isWide, setIsWide] = useState(false);
@@ -70,11 +70,19 @@ export const TxStatusButton: FC<Props> = ({ transaction }) => {
70
70
  <div>Sent</div>
71
71
  <div>{fromAmount}</div>
72
72
  <div>{fromToken}</div>
73
- <img
74
- className="w-5 h-5"
75
- src={fromTokenImage}
76
- alt="source token"
77
- />
73
+
74
+ {fromTokenImage ? (
75
+ <img
76
+ className="w-5 h-5"
77
+ src={fromTokenImage}
78
+ alt="source token"
79
+ />
80
+ ) : (
81
+ <UnknownTokenLogo
82
+ tokenName={"?"}
83
+ className="token-select__generated-logo"
84
+ />
85
+ )}
78
86
  </div>
79
87
  </div>
80
88
  <a
@@ -0,0 +1,14 @@
1
+ interface Props {
2
+ tokenName: string;
3
+ className?: string;
4
+ }
5
+
6
+ export const UnknownTokenLogo = ({ tokenName, className }: Props) => {
7
+ return (
8
+ <div
9
+ className={`w-5 h-5 rounded-full bg-white shadow-sm flex items-center justify-center text-black ${className}`}
10
+ >
11
+ {tokenName.substring(0, 1)}
12
+ </div>
13
+ );
14
+ };
@@ -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
+ };
@@ -30,5 +30,5 @@
30
30
  }
31
31
 
32
32
  .xswap-tx-status {
33
- @apply absolute bottom-5 right-2 flex flex-col gap-3 pl-9 items-end w-full z-50;
33
+ @apply fixed bottom-5 right-2 flex flex-col gap-3 pl-9 items-end w-full z-50;
34
34
  }