@xswap-link/sdk 0.1.1 → 0.1.3

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 (35) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/index.css +98 -39
  3. package/dist/index.d.mts +62 -157
  4. package/dist/index.d.ts +62 -157
  5. package/dist/index.js +962 -1923
  6. package/dist/index.mjs +919 -1887
  7. package/package.json +1 -1
  8. package/src/components/Skeleton/index.tsx +8 -5
  9. package/src/components/TxConfigForm/FeesDetails.tsx +5 -5
  10. package/src/components/TxConfigForm/Form.tsx +20 -14
  11. package/src/components/TxConfigForm/History.tsx +50 -101
  12. package/src/components/TxConfigForm/HistoryCard.tsx +22 -42
  13. package/src/components/TxConfigForm/Summary.tsx +57 -28
  14. package/src/components/TxConfigForm/SwapPanel.tsx +70 -77
  15. package/src/components/TxConfigForm/TokenPicker.tsx +69 -66
  16. package/src/components/TxConfigForm/TopBar.tsx +19 -19
  17. package/src/components/TxConfigForm/UsdPrice.tsx +41 -0
  18. package/src/components/TxConfigForm/index.tsx +1 -2
  19. package/src/components/TxHistoryButton/index.tsx +150 -0
  20. package/src/components/icons/ArrowLeftIcon.tsx +16 -0
  21. package/src/components/icons/ChevronUpIcon.tsx +1 -6
  22. package/src/components/icons/CircularProgressIcon.tsx +13 -15
  23. package/src/components/icons/XSwapLogo.tsx +98 -0
  24. package/src/components/icons/index.ts +2 -0
  25. package/src/components/index.ts +1 -0
  26. package/src/constants/index.ts +3 -2
  27. package/src/contracts/abi/index.ts +0 -2
  28. package/src/contracts/addresses.ts +6 -0
  29. package/src/models/Addresses.ts +1 -0
  30. package/src/models/TransactionHistory.ts +44 -29
  31. package/src/services/integrations/transactions.ts +166 -1
  32. package/src/utils/index.ts +7 -0
  33. package/tailwind.config.js +9 -0
  34. package/tsconfig.json +3 -7
  35. package/src/contracts/abi/XSwapRouter.json +0 -1242
@@ -4,10 +4,9 @@ import { DownArrowIcon } from "../icons";
4
4
  import { Token, Chain, TokenBalances, TokenPrices } from "@src/models";
5
5
  import { TokenPicker } from "./TokenPicker";
6
6
  import { weiToHumanReadable } from "@src/utils";
7
- import { Alert } from "../Alert";
8
7
  import { ChainListElement } from "./ChainListElement";
9
8
  import { BalanceComponent } from "./BalanceComponent";
10
- import BigNumber from "bignumber.js";
9
+ import { UsdPrice } from "@src/components/TxConfigForm/UsdPrice";
11
10
 
12
11
  interface Props {
13
12
  amount: string;
@@ -82,10 +81,12 @@ export const SwapPanel: FC<Props> = ({
82
81
  );
83
82
 
84
83
  return (
85
- <div className="flex flex-col items-start globalBorder rounded-lg bg-[rgba(15,15,15,1)] p-4">
86
- <div className="w-full flex gap-4 items-start justify-between mb-4">
87
- <div className="flex flex-col gap-2 overflow-hidden w-1/2">
88
- <p className="text-white opacity-60 text-sm font-medium">You pay</p>
84
+ <div className="flex justify-between globalBorder rounded-lg bg-[rgba(15,15,15,1)] p-4">
85
+ <div className="flex flex-col justify-between gap-2 overflow-hidden w-1/2">
86
+ <div className="flex flex-col gap-1">
87
+ <p className="text-white opacity-60 text-xs sm:text-sm font-medium">
88
+ You pay
89
+ </p>
89
90
  <input
90
91
  className="p-0 border-none outline-none bg-transparent text-2xl overflow-ellipsis"
91
92
  value={amount}
@@ -102,80 +103,41 @@ export const SwapPanel: FC<Props> = ({
102
103
  placeholder="0"
103
104
  />
104
105
  </div>
105
- <div className="flex flex-col relative items-end gap-2.5 w-1/2 text-xs">
106
- <div
107
- ref={buttonRef}
108
- className="bg-black globalBorder rounded-2xl whitespace-nowrap flex items-center p-2 cursor-pointer gap-2"
109
- onClick={() => setChainListShown((prev) => !prev)}
110
- >
111
- <img
112
- width="16"
113
- height="16"
114
- src={srcChain?.image}
115
- alt={srcChain?.name}
116
- />
117
- <div>{srcChain?.displayName}</div>
118
- <DownArrowIcon />
119
- </div>
120
-
121
- {chainListShown && (
122
- <ul
123
- ref={listRef}
124
- className="bg-black globalBorder rounded-lg whitespace-nowrap z-1 right-0 top-10 px-2 max-w-full max-h-[40vh] overflow-auto absolute text-sm z-20"
125
- >
126
- {chainListOptions.map((chain, index) => (
127
- <ChainListElement
128
- index={index}
129
- length={supportedChains.length}
130
- setSrcChain={setSrcChain}
131
- setChainListShown={setChainListShown}
132
- chain={chain}
133
- />
134
- ))}
135
- </ul>
136
- )}
137
- <div
138
- className="flex gap-2 items-center p-2 max-w-full cursor-pointer bg-black text-white globalBorder rounded-3xl whitespace-nowrap"
139
- onClick={() => {
140
- setTokenListShown((state) => !state);
141
- }}
142
- >
143
- <img
144
- height={16}
145
- width={16}
146
- src={srcToken?.image}
147
- alt={srcToken?.name}
148
- />
149
- <div>{srcToken?.symbol}</div>
150
- <DownArrowIcon />
151
- </div>
152
-
153
- {tokenListShown && (
154
- <TokenPicker
155
- onCloseClick={() => setTokenListShown(false)}
156
- tokens={srcChain?.tokens}
157
- signer={signer}
158
- selectedToken={srcToken}
159
- setSelectedToken={(token) => setSrcToken(token)}
160
- balances={balances}
161
- />
162
- )}
106
+ <div className="flex items-center text-sm text-[rgba(255,255,255,0.6)]">
107
+ <UsdPrice
108
+ prices={prices}
109
+ token={srcToken}
110
+ amount={amount}
111
+ loading={false}
112
+ />
163
113
  </div>
164
114
  </div>
115
+ <div className="flex flex-col relative items-end gap-2.5 w-1/2 text-xs">
116
+ <div
117
+ className="flex gap-2 items-center p-2 max-w-full cursor-pointer bg-black text-white globalBorder rounded-3xl whitespace-nowrap"
118
+ onClick={() => {
119
+ setTokenListShown((state) => !state);
120
+ }}
121
+ >
122
+ <img
123
+ height={16}
124
+ width={16}
125
+ src={srcToken?.image}
126
+ alt={srcToken?.name}
127
+ />
128
+ <div>{srcToken?.symbol}</div>
129
+ <DownArrowIcon />
130
+ </div>
165
131
 
166
- <div className="flex justify-between items-center w-full text-sm text-[rgba(255,255,255,0.6)] relative">
167
- {srcToken ? (
168
- prices && prices[srcToken.address] ? (
169
- <div>
170
- {`$${(Number(amount) * Number(prices[srcToken.address])).toFixed(
171
- 2,
172
- )}`}
173
- </div>
174
- ) : (
175
- <Alert desc="Unknown price" />
176
- )
177
- ) : (
178
- <>$0.00</>
132
+ {tokenListShown && (
133
+ <TokenPicker
134
+ onCloseClick={() => setTokenListShown(false)}
135
+ tokens={srcChain?.tokens}
136
+ signer={signer}
137
+ selectedToken={srcToken}
138
+ setSelectedToken={(token) => setSrcToken(token)}
139
+ balances={balances}
140
+ />
179
141
  )}
180
142
  <div
181
143
  onClick={handleMaxClick}
@@ -185,6 +147,37 @@ export const SwapPanel: FC<Props> = ({
185
147
  <BalanceComponent balances={balances} srcToken={srcToken} />
186
148
  )}
187
149
  </div>
150
+ <div
151
+ ref={buttonRef}
152
+ className="bg-black globalBorder rounded-2xl whitespace-nowrap flex items-center p-2 cursor-pointer gap-2"
153
+ onClick={() => setChainListShown((prev) => !prev)}
154
+ >
155
+ <img
156
+ width="16"
157
+ height="16"
158
+ src={srcChain?.image}
159
+ alt={srcChain?.name}
160
+ />
161
+ <div>{srcChain?.displayName}</div>
162
+ <DownArrowIcon />
163
+ </div>
164
+
165
+ {chainListShown && (
166
+ <ul
167
+ ref={listRef}
168
+ className="bg-black globalBorder rounded-lg whitespace-nowrap z-1 right-0 top-10 px-2 max-w-full max-h-[40vh] overflow-auto absolute text-sm z-20"
169
+ >
170
+ {chainListOptions.map((chain, index) => (
171
+ <ChainListElement
172
+ index={index}
173
+ length={supportedChains.length}
174
+ setSrcChain={setSrcChain}
175
+ setChainListShown={setChainListShown}
176
+ chain={chain}
177
+ />
178
+ ))}
179
+ </ul>
180
+ )}
188
181
  </div>
189
182
  </div>
190
183
  );
@@ -24,7 +24,7 @@ export const TokenPicker: FC<Props> = ({
24
24
  }) => {
25
25
  const [searchValue, setSearchValue] = useState("");
26
26
 
27
- const modalRoot = document.querySelector(".xswap");
27
+ const modalRoot = document.querySelector("#xswap-modal");
28
28
 
29
29
  const onBackdropClick = (e: MouseEvent<HTMLDivElement>) => {
30
30
  e.stopPropagation();
@@ -37,12 +37,24 @@ export const TokenPicker: FC<Props> = ({
37
37
  const filteredTokens = useMemo(() => {
38
38
  const isMatch = (value: string, searchValue: string) =>
39
39
  value.toLowerCase().indexOf(searchValue.toLowerCase()) > -1;
40
- return tokens?.filter(
41
- (token) =>
42
- isMatch(token.symbol, searchValue) ||
43
- isMatch(token.name, searchValue) ||
44
- token.address === searchValue.toLowerCase(),
45
- );
40
+
41
+ return tokens
42
+ ?.filter(
43
+ (token) =>
44
+ isMatch(token.symbol, searchValue) ||
45
+ isMatch(token.name, searchValue) ||
46
+ token.address === searchValue.toLowerCase(),
47
+ )
48
+ .sort((a, b) =>
49
+ a.priority < b.priority
50
+ ? 1
51
+ : balances &&
52
+ balances[a.address] &&
53
+ balances[b.address] &&
54
+ balances[a.address]?.lte(balances[b.address] || "0")
55
+ ? 1
56
+ : -1,
57
+ );
46
58
  }, [searchValue, tokens]);
47
59
 
48
60
  return modalRoot
@@ -94,69 +106,60 @@ export const TokenPicker: FC<Props> = ({
94
106
  <div className="h-[2px] my-0 mx-[-24px] w-[100%+48px] px-12 bg-[rgba(255,255,255,0.1)]" />
95
107
  <div className="overflow-y-scroll h-full mx-[-24px] w-[100%+48px] flex flex-col">
96
108
  {filteredTokens && filteredTokens.length > 0 ? (
97
- filteredTokens
98
- .sort((a, b) =>
99
- balances &&
100
- balances[a.address] &&
101
- balances[b.address] &&
102
- balances[a.address]?.lte(balances[b.address] || "0")
103
- ? 1
104
- : -1,
105
- )
106
- .map((token, index) => (
107
- <div
108
- key={`${index}_${token.address}`}
109
- className={`flex gap-3 py-2 px-[24px] w-full items-center hover:bg-[rgb(25,25,25)] hover:cursor-pointer ${
110
- token.address === selectedToken?.address
111
- ? "bg-[rgb(35,35,35)]"
112
- : ""
113
- }`}
114
- onClick={() => {
115
- setSelectedToken(token);
116
- onCloseClick();
117
- }}
118
- >
119
- {token.image ? (
120
- <img
121
- src={token.image}
122
- alt={token.name}
123
- className="token-picker__all__logo"
124
- />
125
- ) : (
126
- <div className="flex items-center justify-center w-9 h-9 text-[15px] ml-1 rounded-full bg-[#272e40] text-[#e0e7fa]">
127
- {token?.symbol.substring(0, 1)}
109
+ filteredTokens.map((token, index) => (
110
+ <div
111
+ key={`${index}_${token.address}`}
112
+ className={`flex gap-3 py-2 px-[24px] w-full items-center hover:bg-[rgb(25,25,25)] hover:cursor-pointer ${
113
+ token.address === selectedToken?.address
114
+ ? "bg-[rgb(35,35,35)]"
115
+ : ""
116
+ }`}
117
+ onClick={() => {
118
+ setSelectedToken(token);
119
+ onCloseClick();
120
+ }}
121
+ >
122
+ {token.image ? (
123
+ <img
124
+ src={token.image}
125
+ alt={token.name}
126
+ className="token-picker__all__logo"
127
+ />
128
+ ) : (
129
+ <div className="flex items-center justify-center w-9 h-9 text-[15px] ml-1 rounded-full bg-[#272e40] text-[#e0e7fa]">
130
+ {token?.symbol.substring(0, 1)}
131
+ </div>
132
+ )}
133
+ <div className="flex justify-between items-center gap-1 overflow-hidden grow">
134
+ <div className="flex flex-col leading-[16px]">
135
+ <div className="overflow-hidden whitespace-nowrap text-ellipsis text-[15px]">
136
+ {token.name}
128
137
  </div>
129
- )}
130
- <div className="flex justify-between items-center gap-1 overflow-hidden grow">
131
- <div className="flex flex-col leading-[16px]">
132
- <div className="overflow-hidden whitespace-nowrap text-ellipsis text-[15px]">
133
- {token.name}
134
- </div>
135
- <div className="text-[#888] text-[11px]">
136
- {token.symbol}
137
- </div>
138
+ <div className="text-[#888] text-[11px]">
139
+ {token.symbol}
138
140
  </div>
139
- {signer && (
140
- <>
141
- {balances &&
142
- balances[token.address] &&
143
- token.decimals ? (
144
- <div className="text-xs">
145
- {weiToHumanReadable({
146
- amount:
147
- balances[token.address]?.toString() || "0",
148
- decimals: token.decimals,
149
- precisionFractionalPlaces: 4,
150
- })}
151
- </div>
152
- ) : (
153
- <Skeleton w="w-12" h="h-3" />
154
- )}
155
- </>
156
- )}
157
141
  </div>
142
+ {signer && (
143
+ <>
144
+ {balances &&
145
+ balances[token.address] &&
146
+ token.decimals ? (
147
+ <div className="text-xs">
148
+ {weiToHumanReadable({
149
+ amount:
150
+ balances[token.address]?.toString() || "0",
151
+ decimals: token.decimals,
152
+ precisionFractionalPlaces: 4,
153
+ })}
154
+ </div>
155
+ ) : (
156
+ <Skeleton width="w-12" height="h-3" />
157
+ )}
158
+ </>
159
+ )}
158
160
  </div>
159
- ))
161
+ </div>
162
+ ))
160
163
  ) : (
161
164
  <div className="mt-4 flex justify-center">
162
165
  <p className="text-sm text-white">No tokens found.</p>
@@ -16,9 +16,11 @@ export const TopBar: FC<Props> = ({
16
16
  historyTabShown,
17
17
  }) => {
18
18
  return (
19
- <div className="flex w-full justify-between mx-auto pl-4 pr-8 pt-2">
20
- <div className="rounded-lg text-[rgba(255,255,255,0.6)] text-base whitespace-nowrap">
21
- {signer ? `Connected wallet: ${shortAddress(signer)}` : `Disconnected`}
19
+ <div className="flex w-full justify-between items-center mx-auto sm:pl-4 pr-8 pt-2">
20
+ <div className="rounded-lg text-[rgba(255,255,255,0.6)] text-xs sm:text-base whitespace-nowrap">
21
+ {signer
22
+ ? `Connected wallet: ${shortAddress(signer)}`
23
+ : `Wallet disconnected`}
22
24
  </div>
23
25
  <div className="flex gap-2">
24
26
  {!historyTabShown && (
@@ -31,22 +33,20 @@ export const TopBar: FC<Props> = ({
31
33
  </div>
32
34
  </div>
33
35
  )}
34
- {signer && (
35
- <div
36
- onClick={() => setHistoryTabShown((x) => !x)}
37
- className="flex items-center text-sm gap-1 cursor-pointer"
38
- >
39
- {!historyTabShown ? (
40
- <>
41
- <div className="w-7 h-7 rounded-full bg-gradient-to-r from-x_blue_light to-x_blue_dark flex items-center justify-center">
42
- <HistoryIcon />
43
- </div>
44
- </>
45
- ) : (
46
- <div>Back</div>
47
- )}
48
- </div>
49
- )}
36
+ <div
37
+ onClick={() => setHistoryTabShown((x) => !x)}
38
+ className="flex items-center text-sm gap-1 cursor-pointer"
39
+ >
40
+ {!historyTabShown ? (
41
+ <>
42
+ <div className="w-7 h-7 rounded-full bg-gradient-to-r from-x_blue_light to-x_blue_dark flex items-center justify-center">
43
+ <HistoryIcon />
44
+ </div>
45
+ </>
46
+ ) : (
47
+ <div>Back</div>
48
+ )}
49
+ </div>
50
50
  </div>
51
51
  </div>
52
52
  );
@@ -0,0 +1,41 @@
1
+ import { Alert, Skeleton } from "@src/components";
2
+ import { Token, TokenPrices } from "@src/models";
3
+ import { FC, useEffect, useMemo, useState } from "react";
4
+
5
+ type Props = {
6
+ prices: TokenPrices | undefined;
7
+ token: Token | undefined;
8
+ amount: string | undefined;
9
+ loading: boolean;
10
+ };
11
+
12
+ export const UsdPrice: FC<Props> = ({
13
+ prices,
14
+ token,
15
+ amount = "0",
16
+ loading = false,
17
+ }) => {
18
+ const [usdPrice, setUsdPrice] = useState<string>("0.00");
19
+
20
+ useEffect(() => {
21
+ if (token && prices && prices[token.address]) {
22
+ setUsdPrice((Number(amount) * Number(prices[token.address])).toFixed(2));
23
+ }
24
+ }, [token, prices, amount]);
25
+
26
+ return (
27
+ <div className="opacity-60 py-4">
28
+ {loading ? (
29
+ <Skeleton width="w-12" height="h-4" />
30
+ ) : token ? (
31
+ prices && prices[token.address] ? (
32
+ <div>{`$${usdPrice}`}</div>
33
+ ) : (
34
+ <Alert desc="Unknown price" />
35
+ )
36
+ ) : (
37
+ <>$0.00</>
38
+ )}
39
+ </div>
40
+ );
41
+ };
@@ -114,8 +114,7 @@ export const openTxConfigForm = async ({
114
114
  let txConfigFormRoot: Root;
115
115
  if (typeof document !== "undefined") {
116
116
  const xswapElement = document.createElement("div");
117
- xswapElement.setAttribute("id", "txConfigFormRoot");
118
- xswapElement.classList.add("xswap");
117
+ xswapElement.setAttribute("id", "xswap-modal");
119
118
  document.body.appendChild(xswapElement);
120
119
  txConfigFormRoot = createRoot(xswapElement);
121
120
  }
@@ -0,0 +1,150 @@
1
+ import { FC, useState } from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import {
4
+ ArrowLeftIcon,
5
+ ArrowRightIcon,
6
+ CheckIcon,
7
+ CircularProgressIcon,
8
+ } from "../icons";
9
+ import { ArrowUpRightIcon, XSwapLogo } from "../icons";
10
+ import { MonitoredTransaction } from "@src/models";
11
+
12
+ interface Props {
13
+ transaction: MonitoredTransaction;
14
+ }
15
+
16
+ export const TxHistoryButton: FC<Props> = ({ transaction }) => {
17
+ const {
18
+ fromChain,
19
+ fromChainImage,
20
+ fromToken,
21
+ fromTokenImage,
22
+ fromAmount,
23
+ toChain,
24
+ toChainImage,
25
+ isDone,
26
+ txHash,
27
+ explorer,
28
+ } = transaction;
29
+ const [isWide, setIsWide] = useState(false);
30
+ return (
31
+ <div className="flex gap-2" onClick={() => setIsWide((x: boolean) => !x)}>
32
+ {isWide && (
33
+ <div
34
+ className={`flex items-center min-w-60 sm:w-[520px] text-white h-14 px-4 text-sm gap-3 rounded-xl bg-gradient-to-r ${
35
+ isDone
36
+ ? "from-[rgba(76,175,80,0.1)] to-[rgba(46,125,50,0.1)] border border-solid border-x_green_dark"
37
+ : "from-[rgba(54,129,198,0.1)] to-[rgba(43,74,157,0.1)] border border-solid border-x_blue_dark"
38
+ }`}
39
+ >
40
+ <div className="flex justify-between flex-col gap-2 sm:gap-5 sm:flex-row w-full">
41
+ <div className="flex items-center gap-2">
42
+ <img
43
+ className="w-5 h-5"
44
+ src={fromChainImage}
45
+ alt="source chain"
46
+ />
47
+ <div>{fromChain}</div>
48
+ <div className="w-3.5 h-3.5">
49
+ <ArrowRightIcon />
50
+ </div>
51
+ <img className="w-5 h-5" src={toChainImage} alt="to chain" />
52
+ <div>{toChain}</div>
53
+ </div>
54
+
55
+ <div className="flex items-center gap-2">
56
+ <div>Sent</div>
57
+ <div>{fromAmount}</div>
58
+ <div>{fromToken}</div>
59
+ <img
60
+ className="w-5 h-5"
61
+ src={fromTokenImage}
62
+ alt="source token"
63
+ />
64
+ </div>
65
+ </div>
66
+ <a
67
+ href={explorer}
68
+ target="_blank"
69
+ rel="noreferrer"
70
+ className="no-underline cursor-pointer"
71
+ aria-label="Show the transaction in the chain explorer"
72
+ >
73
+ <div className="w-3.5 h-3.5">
74
+ <ArrowUpRightIcon />
75
+ </div>
76
+ </a>
77
+ </div>
78
+ )}
79
+ <div
80
+ className={`text-white rounded-xl cursor-pointer bg-gradient-to-r
81
+ ${
82
+ isDone
83
+ ? "from-[rgba(76,175,80,0.1)] to-[rgba(46,125,50,0.1)] border border-solid border-x_green_dark"
84
+ : "from-[rgba(54,129,198,0.1)] to-[rgba(43,74,157,0.1)] border border-solid border-x_blue_dark"
85
+ }`}
86
+ >
87
+ <div className="flex gap-2 items-center h-14 w-20 justify-center">
88
+ <ArrowLeftIcon />
89
+ <div className="relative flex items-center justify-center w-9 h-9">
90
+ {isDone ? (
91
+ <div className="text-x_green w-5 h-5">
92
+ <CheckIcon />
93
+ </div>
94
+ ) : (
95
+ <>
96
+ <div className="w-5 h-5">
97
+ <XSwapLogo />
98
+ </div>
99
+ <div className="absolute flex items-center justify-center top-0 left-0 right-0 bottom-0 text-white">
100
+ <CircularProgressIcon />
101
+ </div>
102
+ </>
103
+ )}
104
+ </div>
105
+ </div>
106
+ </div>
107
+ </div>
108
+ );
109
+ };
110
+
111
+ let renderedTransactions: MonitoredTransaction[] = [];
112
+
113
+ export const addTransactionToRenderedTransactions = (
114
+ transaction: MonitoredTransaction,
115
+ ) => {
116
+ if (!renderedTransactions.some(({ txHash }) => txHash === transaction.txHash))
117
+ renderedTransactions.push(transaction);
118
+ };
119
+
120
+ export const removeTransactionFromRenderedTransactions = (txHash: string) => {
121
+ const filteredRenderedTransactions = renderedTransactions.filter(
122
+ (item) => item.txHash !== txHash,
123
+ );
124
+ renderedTransactions = [...filteredRenderedTransactions];
125
+ };
126
+
127
+ export const updateTransactionDoneInRenderedTransactions = (txHash: string) => {
128
+ const transaction = renderedTransactions.find(
129
+ (item) => item.txHash === txHash,
130
+ );
131
+ if (transaction) {
132
+ transaction.isDone = true;
133
+ }
134
+ };
135
+
136
+ const historyElement = document.createElement("div");
137
+ historyElement.setAttribute("id", "xswap-history");
138
+ historyElement.setAttribute(
139
+ "class",
140
+ "absolute bottom-5 right-2 flex flex-col gap-3 pl-9 items-end w-full z-50",
141
+ );
142
+ document.body.appendChild(historyElement);
143
+ const txHistoryButtonRoot = createRoot(historyElement);
144
+
145
+ export const renderTxHistoryButtons = () => {
146
+ const buttons = renderedTransactions.map((item) => (
147
+ <TxHistoryButton key={item.txHash} transaction={item} />
148
+ ));
149
+ txHistoryButtonRoot.render(buttons);
150
+ };
@@ -0,0 +1,16 @@
1
+ export const ArrowLeftIcon = () => {
2
+ return (
3
+ <svg
4
+ width="10"
5
+ height="16"
6
+ viewBox="0 0 10 16"
7
+ fill="none"
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ >
10
+ <path
11
+ d="M0.5 8L8.13251 15.5L9.5 14.1562L3.20318 8L9.4682 1.84375L8.10071 0.5L0.5 8Z"
12
+ fill="white"
13
+ />
14
+ </svg>
15
+ );
16
+ };
@@ -1,11 +1,6 @@
1
1
  export const ChevronUpIcon = () => {
2
2
  return (
3
- <svg
4
- height="12"
5
- width="12"
6
- xmlns="http://www.w3.org/2000/svg"
7
- viewBox="0 0 512 512"
8
- >
3
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
9
4
  <path
10
5
  fill="currentColor"
11
6
  d="M233.4 105.4c12.5-12.5 32.8-12.5 45.3 0l192 192c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L256 173.3 86.6 342.6c-12.5 12.5-32.8 12.5-45.3 0s-12.5-32.8 0-45.3l192-192z"
@@ -1,24 +1,22 @@
1
1
  export const CircularProgressIcon = () => {
2
2
  return (
3
3
  <svg
4
- className="animate-spin -ml-1 mr-3 h-10 w-10 text-white"
5
- xmlns="http://www.w3.org/2000/svg"
4
+ className="animate-spin-slow text-white"
5
+ width="33"
6
+ height="33"
7
+ viewBox="0 0 33 33"
6
8
  fill="none"
7
- viewBox="0 0 24 24"
9
+ xmlns="http://www.w3.org/2000/svg"
8
10
  >
9
11
  <circle
10
- className="opacity-25"
11
- cx="12"
12
- cy="12"
13
- r="10"
14
- stroke="currentColor"
15
- strokeWidth="4"
16
- ></circle>
17
- <path
18
- className="opacity-75"
19
- fill="currentColor"
20
- d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
21
- ></path>
12
+ cx="16.5"
13
+ cy="16.5"
14
+ r="15.5"
15
+ stroke="white"
16
+ strokeOpacity="0.2"
17
+ strokeWidth="2"
18
+ />
19
+ <path d="M1 16C1 7.71573 7.71573 1 16 1" stroke="white" strokeWidth="2" />
22
20
  </svg>
23
21
  );
24
22
  };