@xswap-link/sdk 0.13.1 → 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 +7 -0
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.global.js +85 -84
- package/dist/index.js +1553 -1458
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1542 -1444
- 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/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/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
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Modal,
|
|
1
|
+
import { ChevronDownIcon } from "@src/assets/icons";
|
|
2
|
+
import { Modal, TokenLogoWithChain } from "@src/components";
|
|
3
3
|
import { useSwapContext } from "@src/context";
|
|
4
4
|
import { Chain, Token, TokenOption } from "@src/models";
|
|
5
|
+
import { isChainConnectionSupported } from "@src/utils";
|
|
5
6
|
import { useMemo, useState } from "react";
|
|
6
7
|
import { SwapPanelType } from "../../index";
|
|
7
8
|
import { TokenPicker } from "./TokenPicker";
|
|
@@ -16,6 +17,8 @@ type Props = {
|
|
|
16
17
|
export const TokenPanel = ({ chain, token, type, className }: Props) => {
|
|
17
18
|
const {
|
|
18
19
|
bridgeUI,
|
|
20
|
+
srcChain,
|
|
21
|
+
dstChain,
|
|
19
22
|
srcChainTokensOptions,
|
|
20
23
|
srcChainOtherTokensOptions,
|
|
21
24
|
dstChainTokensOptions,
|
|
@@ -67,13 +70,37 @@ export const TokenPanel = ({ chain, token, type, className }: Props) => {
|
|
|
67
70
|
if (type === "source") {
|
|
68
71
|
setSrcToken(token);
|
|
69
72
|
setSrcChain(newChain);
|
|
73
|
+
// The new source chain cannot reach the current destination —
|
|
74
|
+
// reset the destination so the user picks a reachable one.
|
|
75
|
+
if (
|
|
76
|
+
dstChain &&
|
|
77
|
+
!isChainConnectionSupported(newChain, dstChain.chainId, bridgeUI)
|
|
78
|
+
) {
|
|
79
|
+
setDstChain(undefined);
|
|
80
|
+
setDstToken(undefined);
|
|
81
|
+
}
|
|
70
82
|
} else {
|
|
71
83
|
setDstToken(token);
|
|
72
84
|
setDstChain(newChain);
|
|
85
|
+
// The current source cannot reach the new destination chain —
|
|
86
|
+
// reset the source so the user picks a reachable one.
|
|
87
|
+
if (
|
|
88
|
+
srcChain &&
|
|
89
|
+
newChain &&
|
|
90
|
+
!isChainConnectionSupported(srcChain, newChain.chainId, bridgeUI)
|
|
91
|
+
) {
|
|
92
|
+
setSrcChain(undefined);
|
|
93
|
+
setSrcToken(undefined);
|
|
94
|
+
}
|
|
73
95
|
}
|
|
74
96
|
setTokenPickerModalOpen(false);
|
|
75
97
|
};
|
|
76
98
|
|
|
99
|
+
const locked =
|
|
100
|
+
pickerDisabled ||
|
|
101
|
+
integratorLockedDestinationToken ||
|
|
102
|
+
integratorLockedSourceToken;
|
|
103
|
+
|
|
77
104
|
return (
|
|
78
105
|
<>
|
|
79
106
|
{tokenPickerModalOpen && (
|
|
@@ -93,42 +120,41 @@ export const TokenPanel = ({ chain, token, type, className }: Props) => {
|
|
|
93
120
|
|
|
94
121
|
<button
|
|
95
122
|
type="button"
|
|
96
|
-
disabled={
|
|
97
|
-
pickerDisabled ||
|
|
98
|
-
integratorLockedDestinationToken ||
|
|
99
|
-
integratorLockedSourceToken
|
|
100
|
-
}
|
|
123
|
+
disabled={locked}
|
|
101
124
|
onClick={() => {
|
|
102
125
|
setTokenPickerModalOpen(true);
|
|
103
126
|
}}
|
|
104
|
-
className={
|
|
127
|
+
className={`flex items-center gap-1 shrink-0 rounded-lg ${
|
|
128
|
+
locked ? "" : "hover:opacity-80 transition-opacity"
|
|
129
|
+
} ${className || ""}`}
|
|
105
130
|
>
|
|
106
|
-
<div className="flex
|
|
107
|
-
<
|
|
108
|
-
|
|
131
|
+
<div className="flex items-center gap-3">
|
|
132
|
+
<p
|
|
133
|
+
className={`text-sm font-medium leading-6 tracking-[0.01em] text-t_text_primary ${
|
|
134
|
+
token ? "" : "opacity-60"
|
|
135
|
+
}`}
|
|
136
|
+
>
|
|
137
|
+
{token
|
|
138
|
+
? token.symbol
|
|
139
|
+
: type === "destination" && bridgeUI
|
|
140
|
+
? "-"
|
|
141
|
+
: "Select"}
|
|
142
|
+
</p>
|
|
143
|
+
{token && (
|
|
144
|
+
<TokenLogoWithChain
|
|
109
145
|
token={token}
|
|
110
|
-
|
|
111
|
-
|
|
146
|
+
chain={chain}
|
|
147
|
+
tokenLogoClassName="w-10 h-10"
|
|
148
|
+
generatedLogoClassName="w-10 h-10 text-[16px]"
|
|
149
|
+
chainLogoClassName="w-[18px]"
|
|
112
150
|
/>
|
|
113
|
-
|
|
114
|
-
<p className="text-xs opacity-60">Token: </p>
|
|
115
|
-
<p className={`${token ? "" : "opacity-60"}`}>
|
|
116
|
-
{token
|
|
117
|
-
? token.symbol
|
|
118
|
-
: type === "destination" && bridgeUI
|
|
119
|
-
? "-"
|
|
120
|
-
: "Select"}
|
|
121
|
-
</p>
|
|
122
|
-
</div>
|
|
123
|
-
</div>
|
|
124
|
-
{!pickerDisabled &&
|
|
125
|
-
!integratorLockedDestinationToken &&
|
|
126
|
-
!integratorLockedSourceToken && (
|
|
127
|
-
<div className="w-4 h-2 fill-t_text_primary">
|
|
128
|
-
<ArrowDownIcon />
|
|
129
|
-
</div>
|
|
130
|
-
)}
|
|
151
|
+
)}
|
|
131
152
|
</div>
|
|
153
|
+
{!locked && (
|
|
154
|
+
<div className="flex items-center justify-center w-6 h-6 fill-t_text_primary opacity-50 [&_svg]:w-3 [&_svg]:h-3">
|
|
155
|
+
<ChevronDownIcon />
|
|
156
|
+
</div>
|
|
157
|
+
)}
|
|
132
158
|
</button>
|
|
133
159
|
</>
|
|
134
160
|
);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Skeleton } from "@src/components";
|
|
2
|
+
import { useSwapContext } from "@src/context";
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { SwapPanelType } from "../../../SwapView";
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
type: SwapPanelType;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const UsdValue = ({ type }: Props) => {
|
|
11
|
+
const { srcValueUsd, dstValueUsd, isFetchingRoute } = useSwapContext();
|
|
12
|
+
|
|
13
|
+
const valueUsd = useMemo(
|
|
14
|
+
() => (type === "source" ? srcValueUsd : dstValueUsd),
|
|
15
|
+
[dstValueUsd, srcValueUsd, type],
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
if (type === "destination" && isFetchingRoute) {
|
|
19
|
+
return <Skeleton className="w-[80px] h-[16px]" />;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<p className="text-[10px] leading-4 tracking-[0.01em] text-t_text_primary text-opacity-50 whitespace-nowrap">
|
|
24
|
+
{valueUsd ? `${valueUsd} USD` : ""}
|
|
25
|
+
</p>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { ChevronDownIcon } from "@src/assets/icons";
|
|
1
2
|
import { useWallet } from "@src/context/WalletProvider";
|
|
3
|
+
import { useSwapContext } from "@src/context";
|
|
2
4
|
import { SwapPanelType } from "../..";
|
|
3
5
|
import { Chain } from "@src/models";
|
|
4
|
-
import { useCallback } from "react";
|
|
6
|
+
import { useCallback, useMemo } from "react";
|
|
5
7
|
import { shortAddress } from "@src/utils";
|
|
6
8
|
|
|
7
9
|
type Props = {
|
|
@@ -10,7 +12,7 @@ type Props = {
|
|
|
10
12
|
className?: string;
|
|
11
13
|
};
|
|
12
14
|
|
|
13
|
-
export const WalletPanel = ({ chain,
|
|
15
|
+
export const WalletPanel = ({ chain, className }: Props) => {
|
|
14
16
|
const {
|
|
15
17
|
setOpenEVMWalletModal,
|
|
16
18
|
setOpenSolanaWalletModal,
|
|
@@ -19,13 +21,33 @@ export const WalletPanel = ({ chain, type, className }: Props) => {
|
|
|
19
21
|
solana,
|
|
20
22
|
sui,
|
|
21
23
|
} = useWallet();
|
|
24
|
+
const { integrationConfig, hasOnConnectWalletCallback, onConnectWallet } =
|
|
25
|
+
useSwapContext();
|
|
26
|
+
|
|
27
|
+
const openEvmWalletModal = useCallback(() => {
|
|
28
|
+
// Mirror SwapButton's contract: when the integrator supplied their own
|
|
29
|
+
// connect handler and did not opt into the built-in picker, defer to it
|
|
30
|
+
// (e.g. the host dapp's RainbowKit modal) instead of opening the SDK picker.
|
|
31
|
+
if (!integrationConfig.defaultWalletPicker && hasOnConnectWalletCallback) {
|
|
32
|
+
onConnectWallet();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
setOpenEVMWalletModal(true);
|
|
36
|
+
evm.connectWallet();
|
|
37
|
+
}, [
|
|
38
|
+
integrationConfig.defaultWalletPicker,
|
|
39
|
+
hasOnConnectWalletCallback,
|
|
40
|
+
onConnectWallet,
|
|
41
|
+
setOpenEVMWalletModal,
|
|
42
|
+
evm,
|
|
43
|
+
]);
|
|
44
|
+
|
|
22
45
|
const openWalletModal = useCallback(() => {
|
|
23
46
|
if (!chain) {
|
|
24
47
|
return;
|
|
25
48
|
}
|
|
26
49
|
if (chain.ecosystem === "evm") {
|
|
27
|
-
|
|
28
|
-
evm.connectWallet();
|
|
50
|
+
openEvmWalletModal();
|
|
29
51
|
} else if (chain.ecosystem === "solana") {
|
|
30
52
|
setOpenSolanaWalletModal(true);
|
|
31
53
|
solana.connectWallet();
|
|
@@ -34,55 +56,44 @@ export const WalletPanel = ({ chain, type, className }: Props) => {
|
|
|
34
56
|
}
|
|
35
57
|
}, [
|
|
36
58
|
chain,
|
|
37
|
-
|
|
59
|
+
openEvmWalletModal,
|
|
38
60
|
solana,
|
|
39
|
-
setOpenEVMWalletModal,
|
|
40
61
|
setOpenSolanaWalletModal,
|
|
41
62
|
setOpenSuiWalletModal,
|
|
42
63
|
]);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
|
|
65
|
+
const address = useMemo(() => {
|
|
66
|
+
if (!chain) {
|
|
67
|
+
return "";
|
|
68
|
+
}
|
|
69
|
+
if (chain.ecosystem === "evm") {
|
|
70
|
+
return evm.address || "";
|
|
71
|
+
} else if (chain.ecosystem === "solana") {
|
|
72
|
+
return solana.address || "";
|
|
73
|
+
} else if (chain.ecosystem === "sui") {
|
|
74
|
+
return sui.address || "";
|
|
75
|
+
}
|
|
76
|
+
return "";
|
|
77
|
+
}, [chain, evm, solana, sui]);
|
|
78
|
+
|
|
79
|
+
if (!chain) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
55
83
|
return (
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
className
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
</p>
|
|
71
|
-
)}
|
|
72
|
-
</div>
|
|
73
|
-
) : (
|
|
74
|
-
<div className="flex items-center gap-2">
|
|
75
|
-
<p className="text-xs font-medium opacity-60">Receiver:</p>
|
|
76
|
-
{chain && (
|
|
77
|
-
<p className="text-sm font-medium">
|
|
78
|
-
{renderAddress(chain.ecosystem)}
|
|
79
|
-
</p>
|
|
80
|
-
)}
|
|
81
|
-
</div>
|
|
82
|
-
)}
|
|
83
|
-
</div>
|
|
84
|
-
</div>
|
|
85
|
-
</button>
|
|
86
|
-
</>
|
|
84
|
+
<button
|
|
85
|
+
type="button"
|
|
86
|
+
onClick={openWalletModal}
|
|
87
|
+
className={`flex items-center justify-center gap-0.5 px-2 py-1 rounded bg-t_bg_tertiary bg-opacity-5 hover:bg-opacity-10 transition-colors ${
|
|
88
|
+
className || ""
|
|
89
|
+
}`}
|
|
90
|
+
>
|
|
91
|
+
<p className="text-[10px] leading-4 tracking-[0.01em] text-t_text_primary whitespace-nowrap">
|
|
92
|
+
{address ? shortAddress(address) : "Connect"}
|
|
93
|
+
</p>
|
|
94
|
+
<div className="flex items-center justify-center w-4 h-4 fill-t_text_primary opacity-50 [&_svg]:w-2.5 [&_svg]:h-2.5">
|
|
95
|
+
<ChevronDownIcon />
|
|
96
|
+
</div>
|
|
97
|
+
</button>
|
|
87
98
|
);
|
|
88
99
|
};
|
|
@@ -2,9 +2,9 @@ import { useSwapContext } from "@src/context";
|
|
|
2
2
|
import { useMemo } from "react";
|
|
3
3
|
import { SwapPanelType } from "../index";
|
|
4
4
|
import { AmountPanel } from "./AmountPanel";
|
|
5
|
-
import {
|
|
6
|
-
import { MaxPanel } from "./MaxPanel";
|
|
5
|
+
import { Balance } from "./AmountPanel/Balance";
|
|
7
6
|
import { TokenPanel } from "./TokenPanel";
|
|
7
|
+
import { UsdValue } from "./UsdValue";
|
|
8
8
|
import { WalletPanel } from "./WalletPanel";
|
|
9
9
|
|
|
10
10
|
type Props = {
|
|
@@ -24,31 +24,26 @@ export const SwapPanel = ({ type }: Props) => {
|
|
|
24
24
|
);
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
|
-
<div
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
<div
|
|
28
|
+
className={`flex flex-col gap-2 px-4 sm:px-6 py-4 rounded-2xl bg-t_bg_secondary bg-opacity-60 ${
|
|
29
|
+
type === "source"
|
|
30
|
+
? "bg-gradient-to-r from-t_bg_tertiary/5 to-t_bg_tertiary/5 border border-solid border-t_text_primary border-opacity-10"
|
|
31
|
+
: "bg-gradient-to-r from-t_bg_tertiary/[0.03] to-t_bg_tertiary/[0.03]"
|
|
32
|
+
}`}
|
|
33
|
+
>
|
|
34
|
+
<div className="flex gap-2 items-center w-full">
|
|
35
|
+
<p className="text-[10px] leading-4 tracking-[0.01em] text-t_text_primary text-opacity-50">
|
|
36
|
+
{type === "source" ? "Source" : "Destination"}
|
|
37
|
+
</p>
|
|
38
|
+
<WalletPanel chain={chain} type={type} />
|
|
30
39
|
</div>
|
|
31
|
-
<div className="flex
|
|
32
|
-
<TokenPanel
|
|
33
|
-
chain={chain}
|
|
34
|
-
token={token}
|
|
35
|
-
type={type}
|
|
36
|
-
className="w-full flex-grow"
|
|
37
|
-
/>
|
|
38
|
-
<ChainPanel
|
|
39
|
-
chain={chain}
|
|
40
|
-
type={type}
|
|
41
|
-
className="w-full max-w-[160px]"
|
|
42
|
-
/>
|
|
43
|
-
</div>
|
|
44
|
-
<div
|
|
45
|
-
className={`flex justify-between rounded-b-[11px] ${
|
|
46
|
-
type === "destination" &&
|
|
47
|
-
"bg-gradient-to-r from-t_main_accent_light/20 to-t_main_accent_dark/20"
|
|
48
|
-
}`}
|
|
49
|
-
>
|
|
40
|
+
<div className="flex items-center justify-between w-full gap-4">
|
|
50
41
|
<AmountPanel type={type} />
|
|
51
|
-
<
|
|
42
|
+
<TokenPanel chain={chain} token={token} type={type} />
|
|
43
|
+
</div>
|
|
44
|
+
<div className="flex items-center justify-between w-full gap-4">
|
|
45
|
+
<UsdValue type={type} />
|
|
46
|
+
<Balance type={type} />
|
|
52
47
|
</div>
|
|
53
48
|
</div>
|
|
54
49
|
);
|
|
@@ -169,7 +169,12 @@ export const WalletPicker: FC<{
|
|
|
169
169
|
)}
|
|
170
170
|
{ecosystem === Ecosystem.SOLANA && (
|
|
171
171
|
<>
|
|
172
|
-
{wallets
|
|
172
|
+
{wallets
|
|
173
|
+
// MetaMask registers as a Wallet Standard Solana wallet (in more
|
|
174
|
+
// than one variant) but doesn't actually work here, so keep it out
|
|
175
|
+
// of the Solana picker entirely.
|
|
176
|
+
.filter((wallet) => !/metamask/i.test(wallet.adapter.name))
|
|
177
|
+
.map((wallet) => {
|
|
173
178
|
const isConnected =
|
|
174
179
|
publicKey && activeWallet?.adapter.name === wallet.adapter.name;
|
|
175
180
|
return (
|
|
@@ -8,11 +8,12 @@ export type SwapPanelType = "source" | "destination";
|
|
|
8
8
|
export const SwapView = () => {
|
|
9
9
|
return (
|
|
10
10
|
<div className="flex flex-col gap-6 fill-t_text_primary">
|
|
11
|
-
<div className="flex flex-col gap-
|
|
11
|
+
<div className="flex flex-col gap-1.5">
|
|
12
12
|
<SwapPanel type="source" />
|
|
13
13
|
<ReorderButton />
|
|
14
14
|
<SwapPanel type="destination" />
|
|
15
15
|
</div>
|
|
16
|
+
<div className="h-px w-full gradient-sections-separator-container" />
|
|
16
17
|
<FeesPanel />
|
|
17
18
|
<SwapButton />
|
|
18
19
|
</div>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PoweredBy } from "@src/components/PoweredBy";
|
|
1
2
|
import { useSwapContext } from "@src/context";
|
|
2
3
|
import { useMemo } from "react";
|
|
3
4
|
import { Header } from "./Header";
|
|
@@ -25,10 +26,11 @@ export const Swap = ({ onClose }: Props) => {
|
|
|
25
26
|
|
|
26
27
|
return (
|
|
27
28
|
<div
|
|
28
|
-
className={`relative flex flex-col gap-
|
|
29
|
+
className={`relative flex flex-col gap-6 p-5 sm:p-6 text-t_text_primary bg-t_bg_secondary bg-opacity-50 backdrop-blur-[12px] rounded-[20px] border border-solid border-t_text_primary border-opacity-10 flex-1`}
|
|
29
30
|
>
|
|
30
31
|
<Header onClose={onClose} />
|
|
31
|
-
{view}
|
|
32
|
+
<div className="flex flex-col flex-1 min-h-0">{view}</div>
|
|
33
|
+
<PoweredBy />
|
|
32
34
|
</div>
|
|
33
35
|
);
|
|
34
36
|
};
|
|
@@ -5,22 +5,25 @@ type Props = {
|
|
|
5
5
|
|
|
6
6
|
const ToggleButton = ({ checked, onClick }: Props) => {
|
|
7
7
|
return (
|
|
8
|
-
<
|
|
8
|
+
<button
|
|
9
|
+
type="button"
|
|
10
|
+
role="switch"
|
|
11
|
+
aria-checked={checked}
|
|
12
|
+
onClick={onClick}
|
|
13
|
+
className={`relative inline-flex items-center w-12 h-6 p-[3px] rounded-full cursor-pointer transition-colors border-none ${
|
|
14
|
+
checked
|
|
15
|
+
? "bg-gradient-to-r from-t_main_accent_light/40 to-t_main_accent_dark/60"
|
|
16
|
+
: "bg-t_bg_tertiary bg-opacity-10"
|
|
17
|
+
}`}
|
|
18
|
+
>
|
|
9
19
|
<span
|
|
10
|
-
className=
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
checked
|
|
18
|
-
? "translate-x-[12px] bg-t_main_accent_light"
|
|
19
|
-
: "bg-t_bg_tertiary"
|
|
20
|
-
} `}
|
|
21
|
-
></span>
|
|
22
|
-
</span>
|
|
23
|
-
</div>
|
|
20
|
+
className={`w-[18px] h-[18px] rounded-full transition-transform ${
|
|
21
|
+
checked
|
|
22
|
+
? "translate-x-6 bg-t_main_accent_light"
|
|
23
|
+
: "translate-x-0 bg-t_text_primary opacity-40"
|
|
24
|
+
}`}
|
|
25
|
+
></span>
|
|
26
|
+
</button>
|
|
24
27
|
);
|
|
25
28
|
};
|
|
26
29
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Swap } from "@src/components";
|
|
2
2
|
import { getWagmiConfig, waitForInitialization, xpayRoot } from "@src/config";
|
|
3
3
|
import {
|
|
4
4
|
HistoryProvider,
|
|
@@ -87,6 +87,7 @@ export const TxConfigForm = (props: TxConfigFormProps) => {
|
|
|
87
87
|
srcTokenAddr,
|
|
88
88
|
customContractCalls,
|
|
89
89
|
desc,
|
|
90
|
+
widgetTitle,
|
|
90
91
|
dstDisplayTokenAddr,
|
|
91
92
|
supportedChains,
|
|
92
93
|
onSubmit,
|
|
@@ -161,6 +162,7 @@ export const TxConfigForm = (props: TxConfigFormProps) => {
|
|
|
161
162
|
srcTokenAddr,
|
|
162
163
|
customContractCalls,
|
|
163
164
|
desc,
|
|
165
|
+
widgetTitle,
|
|
164
166
|
dstDisplayTokenAddr,
|
|
165
167
|
defaultWalletPicker,
|
|
166
168
|
dstTokenLocked,
|
|
@@ -187,15 +189,13 @@ export const TxConfigForm = (props: TxConfigFormProps) => {
|
|
|
187
189
|
className="top-0 left-0 right-0 bottom-0 bg-[rgba(0,0,0,0.8)] fixed flex flex-col items-center justify-center z-10"
|
|
188
190
|
onMouseDown={onBackdropClick}
|
|
189
191
|
>
|
|
190
|
-
<div className="relative
|
|
192
|
+
<div className="relative rounded-[20px] overflow-auto text-t_text_primary w-x_modal min-w-x_modal max-w-x_modal min-h-[532px] flex flex-col">
|
|
191
193
|
<Swap onSubmit={onSubmit} onClose={onClose} />
|
|
192
|
-
<PoweredBy />
|
|
193
194
|
</div>
|
|
194
195
|
</div>
|
|
195
196
|
) : (
|
|
196
|
-
<div className="
|
|
197
|
+
<div className="rounded-[20px] overflow-auto text-t_text_primary min-h-[532px] w-x_modal min-w-x_modal max-w-x_modal flex flex-col">
|
|
197
198
|
<Swap onSubmit={() => {}} onClose={() => {}} />
|
|
198
|
-
<PoweredBy />
|
|
199
199
|
</div>
|
|
200
200
|
)}
|
|
201
201
|
</TxUIWrapper>
|
|
@@ -21,6 +21,7 @@ const TxWidget = ({
|
|
|
21
21
|
srcToken: srcTokenId,
|
|
22
22
|
customContractCalls = [],
|
|
23
23
|
desc,
|
|
24
|
+
widgetTitle,
|
|
24
25
|
dstDisplayToken,
|
|
25
26
|
lightTheme,
|
|
26
27
|
defaultWalletPicker,
|
|
@@ -116,6 +117,7 @@ const TxWidget = ({
|
|
|
116
117
|
srcTokenAddr={srcTokenAddr}
|
|
117
118
|
customContractCalls={customContractCalls}
|
|
118
119
|
desc={desc}
|
|
120
|
+
widgetTitle={widgetTitle}
|
|
119
121
|
dstDisplayTokenAddr={dstDisplayToken}
|
|
120
122
|
supportedChains={supportedChains}
|
|
121
123
|
overlay={false}
|
|
@@ -166,6 +168,7 @@ export const createTxWidgetWC = () => {
|
|
|
166
168
|
srcToken: "string",
|
|
167
169
|
customContractCalls: "json",
|
|
168
170
|
desc: "string",
|
|
171
|
+
widgetTitle: "string",
|
|
169
172
|
dstDisplayToken: "string",
|
|
170
173
|
lightTheme: "boolean",
|
|
171
174
|
defaultWalletPicker: "boolean",
|
|
@@ -204,6 +207,7 @@ export type TxWidgetWCAttributes = {
|
|
|
204
207
|
"src-token": WidgetIntegrationPayload["srcToken"];
|
|
205
208
|
"custom-contract-calls": string | undefined;
|
|
206
209
|
desc: WidgetIntegrationPayload["desc"];
|
|
210
|
+
"widget-title": WidgetIntegrationPayload["widgetTitle"];
|
|
207
211
|
"dst-display-token": WidgetIntegrationPayload["dstDisplayToken"];
|
|
208
212
|
"light-theme": WidgetIntegrationPayload["lightTheme"];
|
|
209
213
|
"default-wallet-picker": WidgetIntegrationPayload["defaultWalletPicker"];
|
|
@@ -32,6 +32,7 @@ export const TxWidgetWCWrapped = ({
|
|
|
32
32
|
srcToken,
|
|
33
33
|
customContractCalls = [],
|
|
34
34
|
desc,
|
|
35
|
+
widgetTitle,
|
|
35
36
|
dstDisplayToken,
|
|
36
37
|
lightTheme,
|
|
37
38
|
defaultWalletPicker,
|
|
@@ -85,6 +86,7 @@ export const TxWidgetWCWrapped = ({
|
|
|
85
86
|
src-token={srcToken}
|
|
86
87
|
custom-contract-calls={JSON.stringify(customContractCalls)}
|
|
87
88
|
desc={desc}
|
|
89
|
+
widget-title={widgetTitle}
|
|
88
90
|
dst-display-token={dstDisplayToken}
|
|
89
91
|
light-theme={lightTheme}
|
|
90
92
|
default-wallet-picker={defaultWalletPicker}
|
|
@@ -230,6 +230,7 @@ export const HistoryProvider = ({ children }: HistoryProviderProps) => {
|
|
|
230
230
|
|
|
231
231
|
fetchedTransactions.push({
|
|
232
232
|
messageId: entry.messageId,
|
|
233
|
+
receiver: entry.walletAddress,
|
|
233
234
|
hash: entry.source.transactionHash,
|
|
234
235
|
timestamp: timestampMs / 1000,
|
|
235
236
|
sourceChainId: entry.source.blockchainId,
|
package/src/utils/index.ts
CHANGED
|
@@ -77,6 +77,27 @@ export const resolveTokenAddress = (
|
|
|
77
77
|
?.address?.toLowerCase();
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Checks whether a transfer from `srcChain` can reach `dstChainId`,
|
|
82
|
+
* based on the chain-level support lists.
|
|
83
|
+
*/
|
|
84
|
+
export const isChainConnectionSupported = (
|
|
85
|
+
srcChain: Chain | undefined,
|
|
86
|
+
dstChainId: string | undefined,
|
|
87
|
+
bridgeUI: boolean,
|
|
88
|
+
): boolean => {
|
|
89
|
+
if (!srcChain || !dstChainId) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
if (srcChain.chainId === dstChainId) {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
const supportedDst = bridgeUI
|
|
96
|
+
? srcChain.supportedDstForBridge
|
|
97
|
+
: srcChain.supportedDstForSwap;
|
|
98
|
+
return !!supportedDst?.includes(dstChainId);
|
|
99
|
+
};
|
|
100
|
+
|
|
80
101
|
export const sortChains = (chains: Chain[], disabledChainIds: string[]) =>
|
|
81
102
|
[...chains]
|
|
82
103
|
|
package/tailwind.config.js
CHANGED
|
@@ -96,10 +96,10 @@ export default {
|
|
|
96
96
|
x_modal: "var(--modal-width, 340px)",
|
|
97
97
|
},
|
|
98
98
|
width: {
|
|
99
|
-
x_modal: "var(--modal-width)",
|
|
99
|
+
x_modal: "var(--modal-width, 620px)",
|
|
100
100
|
},
|
|
101
101
|
maxWidth: {
|
|
102
|
-
x_modal: "var(--modal-width,
|
|
102
|
+
x_modal: "var(--modal-width, 620px)",
|
|
103
103
|
},
|
|
104
104
|
animation: {
|
|
105
105
|
"spin-slow": "spin 3s linear infinite",
|