@xswap-link/sdk 0.13.0 → 0.14.0
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.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.global.js +90 -89
- package/dist/index.js +1633 -1519
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1597 -1480
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/assets/icons/AdjustmentsIcon.tsx +18 -0
- package/src/assets/icons/CaretDownIcon.tsx +12 -0
- package/src/assets/icons/CaretsUpDownIcon.tsx +13 -0
- package/src/assets/icons/ChainlinkMarkIcon.tsx +17 -0
- package/src/assets/icons/ClockIcon.tsx +18 -0
- package/src/assets/icons/WarningIcon.tsx +16 -0
- package/src/assets/icons/index.ts +6 -0
- package/src/components/Modal/index.tsx +2 -2
- package/src/components/PoweredBy/index.tsx +14 -5
- package/src/components/Swap/Header/Controls/index.tsx +50 -36
- package/src/components/Swap/Header/index.tsx +12 -5
- package/src/components/Swap/HistoryView/ActivityCard/index.tsx +212 -0
- package/src/components/Swap/HistoryView/index.tsx +24 -6
- package/src/components/Swap/ReorderButton/ReorderButton.tsx +5 -7
- package/src/components/Swap/SettingsView/Delivery/index.tsx +27 -28
- package/src/components/Swap/SettingsView/InfiniteApproval/index.tsx +27 -24
- package/src/components/Swap/SettingsView/Slippage/index.tsx +44 -43
- package/src/components/Swap/SettingsView/index.tsx +1 -1
- package/src/components/Swap/SwapView/ConfirmationView/TxOverview/index.tsx +2 -2
- package/src/components/Swap/SwapView/FeesPanel/DeliveryInfo/index.tsx +9 -19
- package/src/components/Swap/SwapView/FeesPanel/Fee/index.tsx +4 -4
- package/src/components/Swap/SwapView/FeesPanel/Fees/index.tsx +5 -9
- package/src/components/Swap/SwapView/FeesPanel/index.tsx +21 -22
- package/src/components/Swap/SwapView/SwapButton/index.tsx +25 -6
- package/src/components/Swap/SwapView/SwapPanel/AmountPanel/Balance/index.tsx +56 -12
- package/src/components/Swap/SwapView/SwapPanel/AmountPanel/index.tsx +42 -41
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/NetworkFilter/index.tsx +157 -0
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/TokenItem/index.tsx +98 -55
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/index.tsx +160 -239
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/index.tsx +57 -31
- package/src/components/Swap/SwapView/SwapPanel/UsdValue/index.tsx +27 -0
- package/src/components/Swap/SwapView/SwapPanel/WalletPanel/index.tsx +60 -49
- package/src/components/Swap/SwapView/SwapPanel/index.tsx +20 -25
- package/src/components/Swap/SwapView/WalletPicker/index.tsx +6 -1
- package/src/components/Swap/SwapView/index.tsx +2 -1
- package/src/components/Swap/index.tsx +4 -2
- package/src/components/ToggleButton/index.tsx +18 -15
- package/src/components/TxConfigForm/index.tsx +5 -5
- package/src/components/TxWidgetWC/index.tsx +4 -0
- package/src/components/TxWidgetWCWrapped/index.tsx +2 -0
- package/src/context/HistoryProvider.tsx +1 -0
- package/src/context/SwapProvider.tsx +94 -67
- package/src/models/TransactionHistory.ts +1 -0
- package/src/models/payloads/ModalIntegrationPayload.ts +1 -0
- package/src/models/payloads/WidgetIntegrationPayload.ts +1 -0
- package/src/utils/index.ts +21 -0
- package/tailwind.config.js +2 -2
- package/src/components/Swap/SwapView/SwapPanel/ChainPanel/ChainPicker/ChainItem/index.tsx +0 -97
- package/src/components/Swap/SwapView/SwapPanel/ChainPanel/ChainPicker/index.tsx +0 -103
- package/src/components/Swap/SwapView/SwapPanel/ChainPanel/index.tsx +0 -65
- package/src/components/Swap/SwapView/SwapPanel/MaxPanel/index.tsx +0 -43
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/QuickPickTokenItem/index.tsx +0 -37
package/package.json
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const AdjustmentsIcon = ({ className }: { className?: string }) => {
|
|
2
|
+
return (
|
|
3
|
+
<svg
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
fill="none"
|
|
6
|
+
viewBox="0 0 24 24"
|
|
7
|
+
strokeWidth={1.5}
|
|
8
|
+
stroke="currentColor"
|
|
9
|
+
className={className}
|
|
10
|
+
>
|
|
11
|
+
<path
|
|
12
|
+
strokeLinecap="round"
|
|
13
|
+
strokeLinejoin="round"
|
|
14
|
+
d="M10.5 6h9.75M10.5 6a1.5 1.5 0 1 1-3 0m3 0a1.5 1.5 0 1 0-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 0 1-3 0m3 0a1.5 1.5 0 0 0-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 0 1-3 0m3 0a1.5 1.5 0 0 0-3 0m-9.75 0h9.75"
|
|
15
|
+
/>
|
|
16
|
+
</svg>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const CaretsUpDownIcon = () => {
|
|
2
|
+
return (
|
|
3
|
+
<svg
|
|
4
|
+
width="10"
|
|
5
|
+
height="16"
|
|
6
|
+
viewBox="0 0 10 16"
|
|
7
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
8
|
+
>
|
|
9
|
+
<path d="M4.99987 16L0 10.9999L5 12.2499L10 10.9999L4.99987 16Z" />
|
|
10
|
+
<path d="M5.00013 0L10 5.00013L5 3.7501L0 5.00013L5.00013 0Z" />
|
|
11
|
+
</svg>
|
|
12
|
+
);
|
|
13
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const ChainlinkMarkIcon = () => {
|
|
2
|
+
return (
|
|
3
|
+
<svg
|
|
4
|
+
width="24"
|
|
5
|
+
height="24"
|
|
6
|
+
viewBox="0 0 24 24"
|
|
7
|
+
fill="none"
|
|
8
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
9
|
+
>
|
|
10
|
+
<rect width="24" height="24" rx="4" fill="white" fillOpacity="0.03" />
|
|
11
|
+
<path
|
|
12
|
+
d="M12.0667 5L6 8.5V15.5L12.0667 19L18.1333 15.5V8.5L12.0667 5ZM15.5632 14.0166L12.0678 16.0331L8.57239 14.0166V9.98344L12.0678 7.96688L15.5632 9.98344V14.0166Z"
|
|
13
|
+
fill="#0847F7"
|
|
14
|
+
/>
|
|
15
|
+
</svg>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const ClockIcon = ({ className }: { className?: string }) => {
|
|
2
|
+
return (
|
|
3
|
+
<svg
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
fill="none"
|
|
6
|
+
viewBox="0 0 24 24"
|
|
7
|
+
strokeWidth={1.5}
|
|
8
|
+
stroke="currentColor"
|
|
9
|
+
className={className}
|
|
10
|
+
>
|
|
11
|
+
<path
|
|
12
|
+
strokeLinecap="round"
|
|
13
|
+
strokeLinejoin="round"
|
|
14
|
+
d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
|
|
15
|
+
/>
|
|
16
|
+
</svg>
|
|
17
|
+
);
|
|
18
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const WarningIcon = ({ className }: { className?: string }) => {
|
|
2
|
+
return (
|
|
3
|
+
<svg
|
|
4
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
5
|
+
viewBox="0 0 24 24"
|
|
6
|
+
fill="currentColor"
|
|
7
|
+
className={className}
|
|
8
|
+
>
|
|
9
|
+
<path
|
|
10
|
+
fillRule="evenodd"
|
|
11
|
+
d="M9.401 3.003c1.155-2 4.043-2 5.197 0l7.355 12.748c1.154 2-.29 4.5-2.599 4.5H4.645c-2.309 0-3.752-2.5-2.598-4.5L9.4 3.003ZM12 8.25a.75.75 0 0 1 .75.75v3.75a.75.75 0 0 1-1.5 0V9a.75.75 0 0 1 .75-.75Zm0 8.25a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z"
|
|
12
|
+
clipRule="evenodd"
|
|
13
|
+
/>
|
|
14
|
+
</svg>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
+
export * from "./AdjustmentsIcon";
|
|
1
2
|
export * from "./ArrowDownIcon";
|
|
3
|
+
export * from "./ClockIcon";
|
|
2
4
|
export * from "./ArrowDownLongIcon";
|
|
3
5
|
export * from "./ArrowLeftIcon";
|
|
4
6
|
export * from "./ArrowRightIcon";
|
|
5
7
|
export * from "./ArrowsExchange";
|
|
6
8
|
export * from "./ArrowUpIcon";
|
|
7
9
|
export * from "./ArrowUpRightIcon";
|
|
10
|
+
export * from "./CaretDownIcon";
|
|
11
|
+
export * from "./CaretsUpDownIcon";
|
|
8
12
|
export * from "./CashbacklIcon";
|
|
9
13
|
export * from "./ChainlinkIcon";
|
|
14
|
+
export * from "./ChainlinkMarkIcon";
|
|
10
15
|
export * from "./CheckIcon";
|
|
11
16
|
export * from "./ChevronDownIcon";
|
|
12
17
|
export * from "./ChevronUpIcon";
|
|
@@ -37,6 +42,7 @@ export * from "./ThumbUpRoundedIcon";
|
|
|
37
42
|
export * from "./TimerIcon";
|
|
38
43
|
export * from "./TokensIcon";
|
|
39
44
|
export * from "./WaitingIcon";
|
|
45
|
+
export * from "./WarningIcon";
|
|
40
46
|
export * from "./WalletConnectIcon";
|
|
41
47
|
export * from "./XMarkIcon";
|
|
42
48
|
export * from "./XPowerIcon";
|
|
@@ -44,10 +44,10 @@ export const Modal: FC<{
|
|
|
44
44
|
}}
|
|
45
45
|
>
|
|
46
46
|
<div
|
|
47
|
-
className="flex flex-col bg-t_bg_primary rounded-
|
|
47
|
+
className="flex flex-col bg-t_bg_primary rounded-[20px] border border-solid border-t_text_primary border-opacity-10 p-5 sm:p-6 w-full min-w-[340px]"
|
|
48
48
|
style={{
|
|
49
49
|
height: overlay ? "600px" : "100%",
|
|
50
|
-
maxWidth: "
|
|
50
|
+
maxWidth: "636px",
|
|
51
51
|
maxHeight: "100%",
|
|
52
52
|
}}
|
|
53
53
|
>
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ChainlinkMarkIcon } from "@src/assets/icons";
|
|
2
2
|
|
|
3
3
|
export const PoweredBy = () => {
|
|
4
4
|
return (
|
|
5
|
-
<div className="flex justify-
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
<div className="flex justify-end items-center">
|
|
6
|
+
<div className="flex items-center gap-2 p-2 rounded-lg bg-gradient-to-r from-t_bg_tertiary/0 to-t_bg_tertiary/5">
|
|
7
|
+
<div className="flex items-center [&_svg]:h-6 [&_svg]:w-6">
|
|
8
|
+
<ChainlinkMarkIcon />
|
|
9
|
+
</div>
|
|
10
|
+
<p className="text-sm whitespace-nowrap leading-6">
|
|
11
|
+
<span className="text-t_text_primary text-opacity-50">
|
|
12
|
+
{`Backed By `}
|
|
13
|
+
</span>
|
|
14
|
+
<span className="text-t_text_primary text-opacity-75">
|
|
15
|
+
Chainlink.
|
|
16
|
+
</span>
|
|
17
|
+
</p>
|
|
9
18
|
</div>
|
|
10
19
|
</div>
|
|
11
20
|
);
|
|
@@ -1,58 +1,72 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CloseIcon,
|
|
3
|
-
HistoryGradientBgIcon,
|
|
4
|
-
SettingsGradientBgIcon,
|
|
5
|
-
} from "@src/assets/icons";
|
|
1
|
+
import { AdjustmentsIcon, ClockIcon, CloseIcon } from "@src/assets/icons";
|
|
6
2
|
import { useSwapContext } from "@src/context";
|
|
3
|
+
import { FC, ReactNode } from "react";
|
|
7
4
|
|
|
8
5
|
type Props = {
|
|
9
6
|
onClose: () => void;
|
|
10
7
|
};
|
|
8
|
+
|
|
9
|
+
const HeaderIconButton: FC<{
|
|
10
|
+
onClick: () => void;
|
|
11
|
+
label: string;
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
}> = ({ onClick, label, children }) => (
|
|
14
|
+
<button
|
|
15
|
+
type="button"
|
|
16
|
+
onClick={onClick}
|
|
17
|
+
aria-label={label}
|
|
18
|
+
className="flex items-center justify-center w-8 h-8 rounded-md bg-t_bg_tertiary bg-opacity-5 text-t_text_primary hover:bg-opacity-10 transition-colors"
|
|
19
|
+
>
|
|
20
|
+
{children}
|
|
21
|
+
</button>
|
|
22
|
+
);
|
|
23
|
+
|
|
11
24
|
export const Controls = ({ onClose }: Props) => {
|
|
12
25
|
const { tab, setTab, overlay } = useSwapContext();
|
|
13
26
|
|
|
14
27
|
return (
|
|
15
|
-
<div className="flex gap-
|
|
28
|
+
<div className="flex gap-2 items-center">
|
|
16
29
|
{tab === "Swap" ? (
|
|
17
30
|
<>
|
|
18
|
-
<
|
|
19
|
-
type="button"
|
|
31
|
+
<HeaderIconButton
|
|
20
32
|
onClick={() => setTab("Settings")}
|
|
21
|
-
|
|
22
|
-
className="fill-white"
|
|
33
|
+
label="Open preferences"
|
|
23
34
|
>
|
|
24
|
-
<
|
|
25
|
-
</
|
|
26
|
-
<
|
|
27
|
-
type="button"
|
|
35
|
+
<AdjustmentsIcon className="w-4 h-4 opacity-50" />
|
|
36
|
+
</HeaderIconButton>
|
|
37
|
+
<HeaderIconButton
|
|
28
38
|
onClick={() => setTab("History")}
|
|
29
|
-
|
|
30
|
-
className="fill-white"
|
|
39
|
+
label="Open activity"
|
|
31
40
|
>
|
|
32
|
-
<
|
|
33
|
-
</
|
|
41
|
+
<ClockIcon className="w-4 h-4 opacity-50" />
|
|
42
|
+
</HeaderIconButton>
|
|
34
43
|
{overlay && (
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
>
|
|
41
|
-
<CloseIcon />
|
|
42
|
-
</button>
|
|
44
|
+
<HeaderIconButton onClick={onClose} label="Close">
|
|
45
|
+
<div className="w-4 h-4 opacity-50 fill-t_text_primary flex items-center justify-center">
|
|
46
|
+
<CloseIcon />
|
|
47
|
+
</div>
|
|
48
|
+
</HeaderIconButton>
|
|
43
49
|
)}
|
|
44
50
|
</>
|
|
45
51
|
) : (
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
<>
|
|
53
|
+
{tab === "Settings" && (
|
|
54
|
+
<HeaderIconButton
|
|
55
|
+
onClick={() => setTab("Settings")}
|
|
56
|
+
label="Preferences"
|
|
57
|
+
>
|
|
58
|
+
<AdjustmentsIcon className="w-4 h-4 opacity-50" />
|
|
59
|
+
</HeaderIconButton>
|
|
60
|
+
)}
|
|
61
|
+
<HeaderIconButton
|
|
62
|
+
onClick={() => setTab("Swap")}
|
|
63
|
+
label="Back to swap"
|
|
64
|
+
>
|
|
65
|
+
<div className="w-4 h-4 opacity-50 fill-t_text_primary flex items-center justify-center">
|
|
66
|
+
<CloseIcon />
|
|
67
|
+
</div>
|
|
68
|
+
</HeaderIconButton>
|
|
69
|
+
</>
|
|
56
70
|
)}
|
|
57
71
|
</div>
|
|
58
72
|
);
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import { useSwapContext } from "@src/context";
|
|
2
2
|
import { Controls } from "./Controls";
|
|
3
3
|
|
|
4
|
+
const DEFAULT_WIDGET_TITLE = "XLane.";
|
|
5
|
+
|
|
4
6
|
type Props = {
|
|
5
7
|
onClose: () => void;
|
|
6
8
|
};
|
|
7
9
|
export const Header = ({ onClose }: Props) => {
|
|
8
|
-
const { tab,
|
|
10
|
+
const { tab, integrationConfig } = useSwapContext();
|
|
11
|
+
|
|
12
|
+
const title =
|
|
13
|
+
tab === "Settings"
|
|
14
|
+
? "Preferences"
|
|
15
|
+
: tab === "History"
|
|
16
|
+
? "My Activity"
|
|
17
|
+
: integrationConfig.widgetTitle || DEFAULT_WIDGET_TITLE;
|
|
9
18
|
|
|
10
19
|
return (
|
|
11
|
-
<div className="flex justify-between
|
|
12
|
-
<div className="text-
|
|
13
|
-
{tab === "Swap" && bridgeUI ? "Bridge" : tab}
|
|
14
|
-
</div>
|
|
20
|
+
<div className="flex justify-between items-center">
|
|
21
|
+
<div className="text-2xl leading-8 tracking-[0.01em]">{title}</div>
|
|
15
22
|
<Controls onClose={onClose} />
|
|
16
23
|
</div>
|
|
17
24
|
);
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import {
|
|
2
|
+
faArrowUpRightFromSquare,
|
|
3
|
+
faChevronRight,
|
|
4
|
+
} from "@fortawesome/free-solid-svg-icons";
|
|
5
|
+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
6
|
+
import {
|
|
7
|
+
Spinner,
|
|
8
|
+
Timer,
|
|
9
|
+
TimerDisplayFormat,
|
|
10
|
+
TokenLogo,
|
|
11
|
+
} from "@src/components";
|
|
12
|
+
import { CCIP_EXPLORER } from "@src/constants";
|
|
13
|
+
import { useSwapContext } from "@src/context";
|
|
14
|
+
import { useWallet } from "@src/context/WalletProvider";
|
|
15
|
+
import { Transaction } from "@src/models";
|
|
16
|
+
import { shortAddress, weiToHumanReadable } from "@src/utils";
|
|
17
|
+
import { format } from "date-fns";
|
|
18
|
+
import { useMemo } from "react";
|
|
19
|
+
|
|
20
|
+
interface Props {
|
|
21
|
+
transaction: Transaction;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const ActivityCard = ({ transaction }: Props) => {
|
|
25
|
+
const { supportedChains, findTokenDataByAddressAndChain, tokenPrices } =
|
|
26
|
+
useSwapContext();
|
|
27
|
+
const { evm, solana } = useWallet();
|
|
28
|
+
|
|
29
|
+
const receiverAddress =
|
|
30
|
+
transaction.receiver ||
|
|
31
|
+
(transaction.sourceChainId === "mainnet-beta"
|
|
32
|
+
? solana.address
|
|
33
|
+
: evm.address);
|
|
34
|
+
|
|
35
|
+
const srcToken = findTokenDataByAddressAndChain(
|
|
36
|
+
transaction.sourceChainId === "mainnet-beta"
|
|
37
|
+
? transaction.tokenAddress
|
|
38
|
+
: transaction.tokenAddress.toLowerCase(),
|
|
39
|
+
transaction.sourceChainId,
|
|
40
|
+
);
|
|
41
|
+
const dstToken = transaction.tokenOutAddress
|
|
42
|
+
? findTokenDataByAddressAndChain(
|
|
43
|
+
transaction.sourceChainId === "mainnet-beta"
|
|
44
|
+
? transaction.tokenOutAddress
|
|
45
|
+
: transaction.tokenOutAddress?.toLowerCase(),
|
|
46
|
+
transaction.targetChainId,
|
|
47
|
+
)
|
|
48
|
+
: undefined;
|
|
49
|
+
|
|
50
|
+
const srcChain = supportedChains.find(
|
|
51
|
+
(chain) => chain.chainId === transaction.sourceChainId,
|
|
52
|
+
);
|
|
53
|
+
const dstChain = supportedChains.find(
|
|
54
|
+
(chain) => chain.chainId === transaction.targetChainId,
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const date = format(
|
|
58
|
+
new Date(transaction.timestamp * 1000),
|
|
59
|
+
"dd.MM.yyyy · hh.mmaa",
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const receivedToken = dstToken || srcToken;
|
|
63
|
+
|
|
64
|
+
const amountToken =
|
|
65
|
+
transaction.tokenOutAmount && dstToken ? dstToken : srcToken;
|
|
66
|
+
|
|
67
|
+
const amount = useMemo(() => {
|
|
68
|
+
if (transaction.tokenOutAmount && dstToken) {
|
|
69
|
+
return weiToHumanReadable({
|
|
70
|
+
amount: transaction.tokenOutAmount,
|
|
71
|
+
decimals: dstToken.decimals,
|
|
72
|
+
precisionFractionalPlaces: 4,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return weiToHumanReadable({
|
|
76
|
+
amount: transaction.amountWei,
|
|
77
|
+
decimals: srcToken?.decimals || 18,
|
|
78
|
+
precisionFractionalPlaces: 4,
|
|
79
|
+
});
|
|
80
|
+
}, [transaction, srcToken, dstToken]);
|
|
81
|
+
|
|
82
|
+
const amountUsd = useMemo(() => {
|
|
83
|
+
const token = dstToken || srcToken;
|
|
84
|
+
const chainId = dstToken
|
|
85
|
+
? transaction.targetChainId
|
|
86
|
+
: transaction.sourceChainId;
|
|
87
|
+
if (!token) return null;
|
|
88
|
+
const price = tokenPrices[chainId]?.[token.address];
|
|
89
|
+
if (!price) return null;
|
|
90
|
+
return (Number(amount.replace(/,/g, "")) * Number(price)).toFixed(2);
|
|
91
|
+
}, [amount, dstToken, srcToken, tokenPrices, transaction]);
|
|
92
|
+
|
|
93
|
+
const explorerUrl = transaction.messageId
|
|
94
|
+
? `${CCIP_EXPLORER}${transaction.messageId}`
|
|
95
|
+
: `${
|
|
96
|
+
supportedChains.find(
|
|
97
|
+
(chain) => chain.chainId === transaction.sourceChainId,
|
|
98
|
+
)?.transactionExplorer
|
|
99
|
+
}/${transaction.hash}`;
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<div className="flex flex-col gap-px pb-2">
|
|
103
|
+
<div className="flex items-center justify-between gap-2 px-4 py-2 rounded-t-xl bg-t_bg_tertiary bg-opacity-5">
|
|
104
|
+
<p className="text-xs leading-[18px] tracking-[0.01em] text-t_text_primary text-opacity-50 whitespace-nowrap">
|
|
105
|
+
{date}
|
|
106
|
+
</p>
|
|
107
|
+
<div className="flex items-center gap-2">
|
|
108
|
+
{transaction.status === "IN_PROGRESS" ? (
|
|
109
|
+
<div className="flex items-center gap-1.5 px-2 py-1 rounded-md bg-t_warning_dark bg-opacity-10 text-t_text_orange">
|
|
110
|
+
<Spinner className="w-3 h-3" />
|
|
111
|
+
<p className="text-xs leading-[18px] whitespace-nowrap">
|
|
112
|
+
{`Est. Time `}
|
|
113
|
+
<Timer
|
|
114
|
+
displayFormat={TimerDisplayFormat.Minutes}
|
|
115
|
+
expiryTimestamp={
|
|
116
|
+
new Date(transaction.estimatedDeliveryTimestamp)
|
|
117
|
+
}
|
|
118
|
+
customTextOnExpire="finalizing"
|
|
119
|
+
/>
|
|
120
|
+
</p>
|
|
121
|
+
</div>
|
|
122
|
+
) : transaction.status === "DONE" ? (
|
|
123
|
+
<p className="text-xs leading-[18px] text-t_text_green px-2 py-1">
|
|
124
|
+
Done
|
|
125
|
+
</p>
|
|
126
|
+
) : transaction.status === "REVERTED" ? (
|
|
127
|
+
<p className="text-xs leading-[18px] text-t_text_red px-2 py-1">
|
|
128
|
+
Reverted
|
|
129
|
+
</p>
|
|
130
|
+
) : null}
|
|
131
|
+
<a
|
|
132
|
+
href={explorerUrl}
|
|
133
|
+
target="_blank"
|
|
134
|
+
rel="noreferrer"
|
|
135
|
+
className="flex items-center justify-center w-6 h-6 rounded-md bg-t_bg_tertiary bg-opacity-5 no-underline text-t_text_primary hover:bg-opacity-10 transition-colors"
|
|
136
|
+
aria-label="Show the transaction in the chain explorer"
|
|
137
|
+
>
|
|
138
|
+
<FontAwesomeIcon
|
|
139
|
+
icon={faArrowUpRightFromSquare}
|
|
140
|
+
className="w-3 h-3 opacity-70"
|
|
141
|
+
/>
|
|
142
|
+
</a>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
<div className="flex items-center gap-3 px-4 py-3 rounded-b-xl bg-t_bg_tertiary bg-opacity-[0.03]">
|
|
146
|
+
<div className="flex items-center shrink-0">
|
|
147
|
+
{dstToken && (
|
|
148
|
+
<div className="flex items-end -mr-2">
|
|
149
|
+
<TokenLogo
|
|
150
|
+
token={srcToken}
|
|
151
|
+
className="min-w-[38px] w-[38px] h-[38px] -mr-2.5"
|
|
152
|
+
generatedLogoClassName="min-w-[38px] w-[38px] h-[38px] text-[15px] -mr-2.5"
|
|
153
|
+
/>
|
|
154
|
+
{srcChain && (
|
|
155
|
+
<img
|
|
156
|
+
src={srcChain.image}
|
|
157
|
+
alt={srcChain.name}
|
|
158
|
+
className="w-4 h-4 shrink-0 border border-solid border-t_bg_secondary rounded-full"
|
|
159
|
+
/>
|
|
160
|
+
)}
|
|
161
|
+
</div>
|
|
162
|
+
)}
|
|
163
|
+
<div className="flex items-end">
|
|
164
|
+
<TokenLogo
|
|
165
|
+
token={receivedToken}
|
|
166
|
+
className="min-w-[38px] w-[38px] h-[38px] -mr-2.5"
|
|
167
|
+
generatedLogoClassName="min-w-[38px] w-[38px] h-[38px] text-[15px] -mr-2.5"
|
|
168
|
+
/>
|
|
169
|
+
{dstChain && (
|
|
170
|
+
<img
|
|
171
|
+
src={dstChain.image}
|
|
172
|
+
alt={dstChain.name}
|
|
173
|
+
className="w-4 h-4 shrink-0 border border-solid border-t_bg_secondary rounded-full"
|
|
174
|
+
/>
|
|
175
|
+
)}
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
<div className="flex justify-between items-center gap-2 w-full min-w-0">
|
|
179
|
+
<div className="text-left min-w-0">
|
|
180
|
+
<div className="flex items-center gap-1.5 text-sm font-medium leading-5 tracking-[0.01em] text-t_text_primary">
|
|
181
|
+
<span>{srcToken?.symbol || "?"}</span>
|
|
182
|
+
{dstToken && (
|
|
183
|
+
<>
|
|
184
|
+
<FontAwesomeIcon
|
|
185
|
+
icon={faChevronRight}
|
|
186
|
+
className="w-2.5 h-2.5 opacity-50"
|
|
187
|
+
/>
|
|
188
|
+
<span>{dstToken.symbol}</span>
|
|
189
|
+
</>
|
|
190
|
+
)}
|
|
191
|
+
</div>
|
|
192
|
+
<div className="flex gap-2 items-center text-xs leading-[18px] tracking-[0.01em] text-t_text_primary text-opacity-50">
|
|
193
|
+
<span className="whitespace-nowrap truncate">
|
|
194
|
+
{`Receiver ${receiverAddress ? shortAddress(receiverAddress) : "-"}`}
|
|
195
|
+
</span>
|
|
196
|
+
</div>
|
|
197
|
+
</div>
|
|
198
|
+
<div className="text-right shrink-0">
|
|
199
|
+
<div className="text-sm font-medium leading-5 tracking-[0.01em] text-t_text_primary">
|
|
200
|
+
{amountToken ? `${amount} ${amountToken.symbol}` : amount}
|
|
201
|
+
</div>
|
|
202
|
+
{amountUsd && (
|
|
203
|
+
<div className="text-xs leading-[18px] tracking-[0.01em] text-t_text_primary text-opacity-50">
|
|
204
|
+
{`${amountUsd} USD`}
|
|
205
|
+
</div>
|
|
206
|
+
)}
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
);
|
|
212
|
+
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Spinner
|
|
1
|
+
import { Spinner } from "@src/components";
|
|
2
2
|
import { useHistory } from "@src/context";
|
|
3
3
|
import { useWallet } from "@src/context/WalletProvider";
|
|
4
4
|
import { useMemo } from "react";
|
|
5
5
|
import { Virtuoso } from "react-virtuoso";
|
|
6
|
+
import { ActivityCard } from "./ActivityCard";
|
|
6
7
|
|
|
7
8
|
export const HistoryView = () => {
|
|
8
9
|
const { history, historyLoadedOnce, solanaHistory, solanaHistoryLoadedOnce } =
|
|
@@ -27,12 +28,29 @@ export const HistoryView = () => {
|
|
|
27
28
|
historyLoadedOnce && (solanaAddress ? solanaHistoryLoadedOnce : true);
|
|
28
29
|
|
|
29
30
|
return isHistoryLoaded ? (
|
|
30
|
-
<div className="
|
|
31
|
-
|
|
31
|
+
<div className="flex flex-col items-center justify-center gap-2 h-full min-h-[320px] text-center">
|
|
32
|
+
<p className="text-sm font-medium text-t_text_primary">
|
|
33
|
+
Nothing here yet...
|
|
34
|
+
</p>
|
|
35
|
+
<p className="text-xs leading-[18px] text-t_text_primary text-opacity-50">
|
|
36
|
+
Your swaps will show up here
|
|
37
|
+
<br />
|
|
38
|
+
once you make the first one.
|
|
39
|
+
</p>
|
|
32
40
|
</div>
|
|
33
41
|
) : (
|
|
34
|
-
<div className="flex justify-center
|
|
42
|
+
<div className="flex flex-col items-center justify-center gap-4 h-full min-h-[320px] text-center">
|
|
35
43
|
<Spinner className="w-8 h-8" />
|
|
44
|
+
<div className="flex flex-col gap-1">
|
|
45
|
+
<p className="text-sm font-medium text-t_text_primary">
|
|
46
|
+
Where's it...
|
|
47
|
+
</p>
|
|
48
|
+
<p className="text-xs leading-[18px] text-t_text_primary text-opacity-50">
|
|
49
|
+
We crunch data for your view.
|
|
50
|
+
<br />
|
|
51
|
+
Please wait a moment.
|
|
52
|
+
</p>
|
|
53
|
+
</div>
|
|
36
54
|
</div>
|
|
37
55
|
);
|
|
38
56
|
}
|
|
@@ -40,9 +58,9 @@ export const HistoryView = () => {
|
|
|
40
58
|
return (
|
|
41
59
|
<Virtuoso
|
|
42
60
|
data={unifiedHistory}
|
|
43
|
-
style={{ height: "
|
|
61
|
+
style={{ height: "424px" }}
|
|
44
62
|
itemContent={(_, transaction) => {
|
|
45
|
-
return <
|
|
63
|
+
return <ActivityCard transaction={transaction} />;
|
|
46
64
|
}}
|
|
47
65
|
/>
|
|
48
66
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CaretsUpDownIcon } from "@src/assets/icons";
|
|
2
2
|
import { useSwapContext } from "@src/context";
|
|
3
3
|
import { FC } from "react";
|
|
4
4
|
|
|
@@ -22,16 +22,14 @@ export const ReorderButton: FC = () => {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
return (
|
|
25
|
-
<div className="h-
|
|
25
|
+
<div className="h-0 w-full relative z-[1]">
|
|
26
26
|
<button
|
|
27
27
|
onClick={onReorderClick}
|
|
28
28
|
aria-label="Switch target token with the source token"
|
|
29
|
-
className="absolute -translate-
|
|
29
|
+
className="absolute left-1/2 -translate-x-1/2 -translate-y-1/2 flex items-center justify-center w-8 h-8 rounded-md bg-t_bg_secondary border border-solid border-t_text_primary border-opacity-10 hover:border-opacity-25 transition-colors"
|
|
30
30
|
>
|
|
31
|
-
<div className="
|
|
32
|
-
<
|
|
33
|
-
<ArrowsExchange />
|
|
34
|
-
</div>
|
|
31
|
+
<div className="flex fill-t_text_primary opacity-75 [&_svg]:w-2.5 [&_svg]:h-4">
|
|
32
|
+
<CaretsUpDownIcon />
|
|
35
33
|
</div>
|
|
36
34
|
</button>
|
|
37
35
|
</div>
|