@xswap-link/sdk 0.7.0 → 0.8.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 +10 -0
- package/dist/index.d.mts +122 -70
- package/dist/index.d.ts +122 -70
- package/dist/index.global.js +686 -281
- package/dist/index.js +10 -10
- package/dist/index.mjs +10 -10
- package/package.json +1 -1
- package/src/assets/icons/ArrowsExchange.tsx +18 -0
- package/src/assets/icons/index.ts +1 -0
- package/src/components/Swap/Header/index.tsx +4 -2
- package/src/components/Swap/HistoryView/index.tsx +2 -2
- package/src/components/Swap/ReorderButton/ReorderButton.tsx +37 -0
- package/src/components/Swap/SwapView/ConfirmationView/TxOverview/ArrowIcon.tsx +1 -1
- package/src/components/Swap/SwapView/SwapButton/index.tsx +3 -1
- package/src/components/Swap/SwapView/SwapPanel/ChainPanel/ChainPicker/ChainItem/index.tsx +55 -22
- package/src/components/Swap/SwapView/SwapPanel/ChainPanel/ChainPicker/index.tsx +71 -6
- package/src/components/Swap/SwapView/SwapPanel/ChainPanel/index.tsx +68 -15
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/index.tsx +10 -2
- package/src/components/Swap/SwapView/SwapPanel/TokenPanel/index.tsx +31 -11
- package/src/components/Swap/SwapView/SwapPanel/index.tsx +8 -3
- package/src/components/Swap/SwapView/index.tsx +3 -3
- package/src/components/Swap/index.tsx +1 -1
- package/src/components/TxConfigForm/index.tsx +57 -4
- package/src/components/TxWidgetWC/index.tsx +47 -2
- package/src/components/TxWidgetWCWrapped/index.tsx +33 -1
- package/src/config/index.ts +1 -1
- package/src/context/SwapProvider.tsx +177 -27
- package/src/models/BridgeTokensDictionary.ts +7 -0
- package/src/models/TokenData.ts +3 -1
- package/src/models/index.ts +6 -5
- package/src/models/payloads/ModalIntegrationPayload.ts +15 -1
- package/src/models/payloads/WidgetIntegrationPayload.ts +15 -1
- package/src/services/api.ts +6 -1
- package/src/services/integrations/transactions.ts +20 -0
- package/src/types/global.d.ts +15 -0
- package/src/utils/validation.ts +367 -0
- package/tsconfig.json +3 -2
|
@@ -1,16 +1,16 @@
|
|
|
1
|
+
import { ReorderButton } from "../ReorderButton/ReorderButton";
|
|
1
2
|
import { FeesPanel } from "./FeesPanel";
|
|
2
3
|
import { SwapButton } from "./SwapButton";
|
|
3
4
|
import { SwapPanel } from "./SwapPanel";
|
|
4
|
-
import { ArrowIcon } from "@src/components/Swap/SwapView/ConfirmationView/TxOverview/ArrowIcon";
|
|
5
5
|
|
|
6
6
|
export type SwapPanelType = "source" | "destination";
|
|
7
7
|
|
|
8
8
|
export const SwapView = () => {
|
|
9
9
|
return (
|
|
10
10
|
<div className="flex flex-col gap-2 fill-t_text_primary">
|
|
11
|
-
<div className="
|
|
11
|
+
<div className="flex flex-col gap-5">
|
|
12
12
|
<SwapPanel type="source" />
|
|
13
|
-
<
|
|
13
|
+
<ReorderButton />
|
|
14
14
|
<SwapPanel type="destination" />
|
|
15
15
|
</div>
|
|
16
16
|
<FeesPanel />
|
|
@@ -25,7 +25,7 @@ export const Swap = ({ onClose }: Props) => {
|
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
27
|
<div
|
|
28
|
-
className={`flex flex-col gap-5 p-4
|
|
28
|
+
className={`relative flex flex-col gap-5 p-4 text-t_text_primary bg-t_bg_primary rounded-3xl flex-1`}
|
|
29
29
|
>
|
|
30
30
|
<Header onClose={onClose} />
|
|
31
31
|
{view}
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
SwapProvider,
|
|
6
6
|
TransactionProvider,
|
|
7
7
|
TxUIWrapper,
|
|
8
|
+
useHistory,
|
|
8
9
|
} from "@src/context";
|
|
9
10
|
import { Chain, ModalIntegrationPayload, Route } from "@src/models";
|
|
10
11
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
@@ -23,7 +24,6 @@ export type TxConfigFormPayload = Omit<
|
|
|
23
24
|
srcTokenAddr?: string;
|
|
24
25
|
dstDisplayTokenAddr?: string;
|
|
25
26
|
supportedChains: Chain[];
|
|
26
|
-
defaultWalletPicker?: boolean;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
const queryClient = new QueryClient();
|
|
@@ -44,6 +44,27 @@ const WagmiReload: FC = () => {
|
|
|
44
44
|
return <></>;
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
+
const PendingTransactionsEmitter: FC<{
|
|
48
|
+
onPendingTransactionsChange: ModalIntegrationPayload["onPendingTransactionsChange"];
|
|
49
|
+
}> = ({ onPendingTransactionsChange }) => {
|
|
50
|
+
const { history } = useHistory();
|
|
51
|
+
|
|
52
|
+
const pendingTransactions = useMemo(
|
|
53
|
+
() => history.filter((entry) => entry.status === "IN_PROGRESS"),
|
|
54
|
+
[history],
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
if (onPendingTransactionsChange) {
|
|
59
|
+
onPendingTransactionsChange(pendingTransactions);
|
|
60
|
+
} else if (window.xPayOnPendingTransactionsChange) {
|
|
61
|
+
window.xPayOnPendingTransactionsChange(pendingTransactions);
|
|
62
|
+
}
|
|
63
|
+
}, [onPendingTransactionsChange, pendingTransactions]);
|
|
64
|
+
|
|
65
|
+
return <></>;
|
|
66
|
+
};
|
|
67
|
+
|
|
47
68
|
export const TxConfigForm = ({
|
|
48
69
|
integratorId,
|
|
49
70
|
dstChainId,
|
|
@@ -60,6 +81,16 @@ export const TxConfigForm = ({
|
|
|
60
81
|
lightTheme,
|
|
61
82
|
defaultWalletPicker,
|
|
62
83
|
styles,
|
|
84
|
+
onPendingTransactionsChange,
|
|
85
|
+
dstTokenLocked,
|
|
86
|
+
dstChainLocked,
|
|
87
|
+
srcTokenLocked,
|
|
88
|
+
srcChainLocked,
|
|
89
|
+
onDstTokenChange,
|
|
90
|
+
onDstChainChange,
|
|
91
|
+
onSrcTokenChange,
|
|
92
|
+
onSrcChainChange,
|
|
93
|
+
bridge,
|
|
63
94
|
}: TxConfigFormPayload &
|
|
64
95
|
(
|
|
65
96
|
| {
|
|
@@ -102,6 +133,9 @@ export const TxConfigForm = ({
|
|
|
102
133
|
<QueryClientProvider client={queryClient}>
|
|
103
134
|
<WagmiReload />
|
|
104
135
|
<HistoryProvider>
|
|
136
|
+
<PendingTransactionsEmitter
|
|
137
|
+
onPendingTransactionsChange={onPendingTransactionsChange}
|
|
138
|
+
/>
|
|
105
139
|
<SwapProvider
|
|
106
140
|
integrationConfig={{
|
|
107
141
|
integratorId,
|
|
@@ -113,6 +147,15 @@ export const TxConfigForm = ({
|
|
|
113
147
|
desc,
|
|
114
148
|
dstDisplayTokenAddr,
|
|
115
149
|
defaultWalletPicker,
|
|
150
|
+
dstTokenLocked,
|
|
151
|
+
dstChainLocked,
|
|
152
|
+
srcTokenLocked,
|
|
153
|
+
srcChainLocked,
|
|
154
|
+
onDstTokenChange,
|
|
155
|
+
onDstChainChange,
|
|
156
|
+
onSrcTokenChange,
|
|
157
|
+
onSrcChainChange,
|
|
158
|
+
bridge,
|
|
116
159
|
}}
|
|
117
160
|
supportedChains={supportedChains}
|
|
118
161
|
wagmiConfig={wagmiConfig}
|
|
@@ -122,16 +165,16 @@ export const TxConfigForm = ({
|
|
|
122
165
|
<TxUIWrapper>
|
|
123
166
|
{overlay ? (
|
|
124
167
|
<div
|
|
125
|
-
className="top-0 left-0 right-0 bottom-0 bg-[rgba(0,0,0,0.8)] fixed flex items-center justify-center z-10"
|
|
168
|
+
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"
|
|
126
169
|
onMouseDown={onBackdropClick}
|
|
127
170
|
>
|
|
128
|
-
<div className="relative bg-t_bg_primary rounded-3xl overflow-auto text-t_text_primary border-2 border-solid border-[rgba(255,255,255,0.1)] min-w-x_modal max-w-x_modal min-h-[
|
|
171
|
+
<div className="relative bg-t_bg_primary rounded-3xl overflow-auto text-t_text_primary border-2 border-solid border-[rgba(255,255,255,0.1)] min-w-x_modal max-w-x_modal min-h-[532px] w-full">
|
|
129
172
|
<Swap onSubmit={onSubmit} onClose={onClose} />
|
|
130
173
|
<PoweredBy />
|
|
131
174
|
</div>
|
|
132
175
|
</div>
|
|
133
176
|
) : (
|
|
134
|
-
<div className="bg-t_bg_primary rounded-3xl overflow-auto text-t_text_primary border-2 border-solid border-[rgba(255,255,255,0.1)] min-h-[
|
|
177
|
+
<div className="bg-t_bg_primary rounded-3xl overflow-auto text-t_text_primary border-2 border-solid border-[rgba(255,255,255,0.1)] min-h-[532px] w-full flex flex-col">
|
|
135
178
|
<Swap onSubmit={() => {}} onClose={() => {}} />
|
|
136
179
|
<PoweredBy />
|
|
137
180
|
</div>
|
|
@@ -159,6 +202,11 @@ export const openTxConfigForm = async ({
|
|
|
159
202
|
lightTheme,
|
|
160
203
|
defaultWalletPicker,
|
|
161
204
|
styles,
|
|
205
|
+
onPendingTransactionsChange,
|
|
206
|
+
dstTokenLocked,
|
|
207
|
+
dstChainLocked,
|
|
208
|
+
srcTokenLocked,
|
|
209
|
+
srcChainLocked,
|
|
162
210
|
}: TxConfigFormPayload): Promise<Route> => {
|
|
163
211
|
try {
|
|
164
212
|
if (xpayRoot === null) {
|
|
@@ -197,6 +245,11 @@ export const openTxConfigForm = async ({
|
|
|
197
245
|
}}
|
|
198
246
|
overlay={true}
|
|
199
247
|
defaultWalletPicker={defaultWalletPicker}
|
|
248
|
+
onPendingTransactionsChange={onPendingTransactionsChange}
|
|
249
|
+
dstTokenLocked={dstTokenLocked}
|
|
250
|
+
dstChainLocked={dstChainLocked}
|
|
251
|
+
srcTokenLocked={srcTokenLocked}
|
|
252
|
+
srcChainLocked={srcChainLocked}
|
|
200
253
|
/>,
|
|
201
254
|
);
|
|
202
255
|
});
|
|
@@ -5,12 +5,12 @@ import {
|
|
|
5
5
|
WidgetIntegrationPayload,
|
|
6
6
|
} from "@src/models";
|
|
7
7
|
import { getChains } from "@src/services";
|
|
8
|
+
import { isServer } from "@src/utils";
|
|
8
9
|
import { createWebComponent } from "@src/utils/webComponents";
|
|
9
10
|
import { useEffect, useState } from "react";
|
|
10
11
|
import { Spinner } from "../Spinner";
|
|
11
12
|
import { TxConfigForm } from "../TxConfigForm";
|
|
12
13
|
import CSS from "../global.css";
|
|
13
|
-
import { isServer } from "@src/utils";
|
|
14
14
|
|
|
15
15
|
const TxWidget = ({
|
|
16
16
|
integratorId,
|
|
@@ -24,6 +24,16 @@ const TxWidget = ({
|
|
|
24
24
|
lightTheme,
|
|
25
25
|
defaultWalletPicker,
|
|
26
26
|
styles,
|
|
27
|
+
onPendingTransactionsChange,
|
|
28
|
+
dstTokenLocked,
|
|
29
|
+
dstChainLocked,
|
|
30
|
+
srcTokenLocked,
|
|
31
|
+
srcChainLocked,
|
|
32
|
+
onDstTokenChange,
|
|
33
|
+
onDstChainChange,
|
|
34
|
+
onSrcTokenChange,
|
|
35
|
+
onSrcChainChange,
|
|
36
|
+
bridge,
|
|
27
37
|
}: WidgetIntegrationPayload) => {
|
|
28
38
|
const [loading, setLoading] = useState(true);
|
|
29
39
|
const [supportedChains, setSupportedChains] = useState<Chain[]>([]);
|
|
@@ -57,7 +67,9 @@ const TxWidget = ({
|
|
|
57
67
|
<style>{CSS}</style>
|
|
58
68
|
|
|
59
69
|
{loading ? (
|
|
60
|
-
<
|
|
70
|
+
<div className="min-h-[532px] w-full flex items-center justify-center">
|
|
71
|
+
<Spinner className="w-10 h-10" />
|
|
72
|
+
</div>
|
|
61
73
|
) : (
|
|
62
74
|
<TxConfigForm
|
|
63
75
|
integratorId={integratorId}
|
|
@@ -73,6 +85,16 @@ const TxWidget = ({
|
|
|
73
85
|
lightTheme={lightTheme}
|
|
74
86
|
defaultWalletPicker={defaultWalletPicker}
|
|
75
87
|
styles={parsedStyles}
|
|
88
|
+
onPendingTransactionsChange={onPendingTransactionsChange}
|
|
89
|
+
dstTokenLocked={dstTokenLocked}
|
|
90
|
+
dstChainLocked={dstChainLocked}
|
|
91
|
+
srcTokenLocked={srcTokenLocked}
|
|
92
|
+
srcChainLocked={srcChainLocked}
|
|
93
|
+
onDstTokenChange={onDstTokenChange}
|
|
94
|
+
onDstChainChange={onDstChainChange}
|
|
95
|
+
onSrcTokenChange={onSrcTokenChange}
|
|
96
|
+
onSrcChainChange={onSrcChainChange}
|
|
97
|
+
bridge={bridge}
|
|
76
98
|
/>
|
|
77
99
|
)}
|
|
78
100
|
</>
|
|
@@ -106,6 +128,16 @@ export const createTxWidgetWC = () => {
|
|
|
106
128
|
lightTheme: "boolean",
|
|
107
129
|
defaultWalletPicker: "boolean",
|
|
108
130
|
styles: "json",
|
|
131
|
+
onPendingTransactionsChange: "function",
|
|
132
|
+
dstTokenLocked: "boolean",
|
|
133
|
+
dstChainLocked: "boolean",
|
|
134
|
+
srcTokenLocked: "boolean",
|
|
135
|
+
srcChainLocked: "boolean",
|
|
136
|
+
bridge: "boolean",
|
|
137
|
+
onDstTokenChange: "function",
|
|
138
|
+
onDstChainChange: "function",
|
|
139
|
+
onSrcTokenChange: "function",
|
|
140
|
+
onSrcChainChange: "function",
|
|
109
141
|
},
|
|
110
142
|
});
|
|
111
143
|
|
|
@@ -116,6 +148,8 @@ export const createTxWidgetWC = () => {
|
|
|
116
148
|
return TxWidgetWC;
|
|
117
149
|
};
|
|
118
150
|
|
|
151
|
+
// Most fields are required here to enforce adding them in TxWidgetWCWrapped.
|
|
152
|
+
// callbacks are optional, because it will not be passed in TxWidgetWCWrapped.
|
|
119
153
|
export type TxWidgetWCAttributes = {
|
|
120
154
|
"integrator-id": WidgetIntegrationPayload["integratorId"];
|
|
121
155
|
"dst-chain": WidgetIntegrationPayload["dstChain"];
|
|
@@ -128,4 +162,15 @@ export type TxWidgetWCAttributes = {
|
|
|
128
162
|
"light-theme": WidgetIntegrationPayload["lightTheme"];
|
|
129
163
|
"default-wallet-picker": WidgetIntegrationPayload["defaultWalletPicker"];
|
|
130
164
|
styles: string | undefined;
|
|
165
|
+
"on-pending-transactions-change"?:
|
|
166
|
+
| WidgetIntegrationPayload["onPendingTransactionsChange"];
|
|
167
|
+
"dst-token-locked": WidgetIntegrationPayload["dstTokenLocked"] | undefined;
|
|
168
|
+
"dst-chain-locked": WidgetIntegrationPayload["dstChainLocked"] | undefined;
|
|
169
|
+
"src-token-locked": WidgetIntegrationPayload["srcTokenLocked"] | undefined;
|
|
170
|
+
"src-chain-locked": WidgetIntegrationPayload["srcChainLocked"] | undefined;
|
|
171
|
+
"on-dst-token-change"?: WidgetIntegrationPayload["onDstTokenChange"];
|
|
172
|
+
"on-dst-chain-change"?: WidgetIntegrationPayload["onDstChainChange"];
|
|
173
|
+
"on-src-token-change"?: WidgetIntegrationPayload["onSrcTokenChange"];
|
|
174
|
+
"on-src-chain-change"?: WidgetIntegrationPayload["onSrcChainChange"];
|
|
175
|
+
bridge: WidgetIntegrationPayload["bridge"] | undefined;
|
|
131
176
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { WidgetIntegrationPayload } from "@src/models";
|
|
2
|
-
import { createTxWidgetWC, TxWidgetWCAttributes } from "../TxWidgetWC";
|
|
3
2
|
import { isServer } from "@tanstack/react-query";
|
|
3
|
+
import { useEffect } from "react";
|
|
4
|
+
import { createTxWidgetWC, TxWidgetWCAttributes } from "../TxWidgetWC";
|
|
4
5
|
|
|
5
6
|
const TxWidgetWC = createTxWidgetWC();
|
|
6
7
|
|
|
@@ -35,7 +36,33 @@ export const TxWidgetWCWrapped = ({
|
|
|
35
36
|
lightTheme,
|
|
36
37
|
defaultWalletPicker,
|
|
37
38
|
styles,
|
|
39
|
+
onPendingTransactionsChange,
|
|
40
|
+
dstTokenLocked,
|
|
41
|
+
dstChainLocked,
|
|
42
|
+
srcTokenLocked,
|
|
43
|
+
srcChainLocked,
|
|
44
|
+
onDstTokenChange,
|
|
45
|
+
onDstChainChange,
|
|
46
|
+
onSrcTokenChange,
|
|
47
|
+
onSrcChainChange,
|
|
48
|
+
bridge,
|
|
38
49
|
}: WidgetIntegrationPayload) => {
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
// We couldn't find a way to pass a function to the web component created by @r2wc/core.
|
|
52
|
+
// It is assigned to window to be accessed later from within the web component.
|
|
53
|
+
window.xPayOnPendingTransactionsChange = onPendingTransactionsChange;
|
|
54
|
+
window.xPayOnDstTokenChange = onDstTokenChange;
|
|
55
|
+
window.xPayOnDstChainChange = onDstChainChange;
|
|
56
|
+
window.xPayOnSrcTokenChange = onSrcTokenChange;
|
|
57
|
+
window.xPayOnSrcChainChange = onSrcChainChange;
|
|
58
|
+
}, [
|
|
59
|
+
onPendingTransactionsChange,
|
|
60
|
+
onDstTokenChange,
|
|
61
|
+
onDstChainChange,
|
|
62
|
+
onSrcTokenChange,
|
|
63
|
+
onSrcChainChange,
|
|
64
|
+
]);
|
|
65
|
+
|
|
39
66
|
return (
|
|
40
67
|
<xpay-widget
|
|
41
68
|
integrator-id={integratorId}
|
|
@@ -49,6 +76,11 @@ export const TxWidgetWCWrapped = ({
|
|
|
49
76
|
light-theme={lightTheme}
|
|
50
77
|
default-wallet-picker={defaultWalletPicker}
|
|
51
78
|
styles={typeof styles === "string" ? styles : JSON.stringify(styles)}
|
|
79
|
+
dst-token-locked={dstTokenLocked}
|
|
80
|
+
dst-chain-locked={dstChainLocked}
|
|
81
|
+
src-token-locked={srcTokenLocked}
|
|
82
|
+
src-chain-locked={srcChainLocked}
|
|
83
|
+
bridge={bridge}
|
|
52
84
|
></xpay-widget>
|
|
53
85
|
);
|
|
54
86
|
};
|
package/src/config/index.ts
CHANGED
|
@@ -8,6 +8,8 @@ import {
|
|
|
8
8
|
} from "@src/constants";
|
|
9
9
|
import { ADDRESSES } from "@src/contracts";
|
|
10
10
|
import {
|
|
11
|
+
BridgeToken,
|
|
12
|
+
BridgeTokensDictionary,
|
|
11
13
|
Chain,
|
|
12
14
|
Route,
|
|
13
15
|
Token,
|
|
@@ -16,7 +18,12 @@ import {
|
|
|
16
18
|
Transaction,
|
|
17
19
|
Web3Environment,
|
|
18
20
|
} from "@src/models";
|
|
19
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
getBalances,
|
|
23
|
+
getBridgeTokens,
|
|
24
|
+
getPrices,
|
|
25
|
+
getRoute,
|
|
26
|
+
} from "@src/services";
|
|
20
27
|
import {
|
|
21
28
|
deepMergeObjects,
|
|
22
29
|
getBalanceOf,
|
|
@@ -25,6 +32,7 @@ import {
|
|
|
25
32
|
safeBigNumberFrom,
|
|
26
33
|
weiToHumanReadable,
|
|
27
34
|
} from "@src/utils";
|
|
35
|
+
import { mapToValidPath } from "@src/utils/validation";
|
|
28
36
|
import BigNumberJS from "bignumber.js";
|
|
29
37
|
import { BigNumber, constants } from "ethers";
|
|
30
38
|
import {
|
|
@@ -44,6 +52,7 @@ import { useHistory } from "./HistoryProvider";
|
|
|
44
52
|
|
|
45
53
|
type Tab = "Swap" | "History" | "Settings";
|
|
46
54
|
type SwapContext = {
|
|
55
|
+
bridgeUI: boolean;
|
|
47
56
|
integrationConfig: Partial<TxConfigFormPayload>;
|
|
48
57
|
wagmiConfig: Config;
|
|
49
58
|
supportedChains: Chain[];
|
|
@@ -53,22 +62,22 @@ type SwapContext = {
|
|
|
53
62
|
error: string;
|
|
54
63
|
setError: Dispatch<SetStateAction<string>>;
|
|
55
64
|
feeToken: Token | undefined;
|
|
56
|
-
srcChainProvided: boolean;
|
|
57
65
|
srcChain: Chain | undefined;
|
|
58
66
|
setSrcChain: Dispatch<SetStateAction<Chain | undefined>>;
|
|
59
67
|
srcChainTokensOptions: TokenOption[];
|
|
60
68
|
srcChainOtherTokensOptions: TokenOption[];
|
|
61
69
|
srcChainTokensPrices: TokenPrices;
|
|
62
70
|
dstChainTokensPrices: TokenPrices;
|
|
63
|
-
srcTokenProvided: boolean;
|
|
64
71
|
srcToken: Token | undefined;
|
|
65
72
|
setSrcToken: Dispatch<SetStateAction<Token | undefined>>;
|
|
66
|
-
dstChainProvided: boolean;
|
|
67
73
|
dstChain: Chain | undefined;
|
|
68
74
|
setDstChain: Dispatch<SetStateAction<Chain | undefined>>;
|
|
69
75
|
dstChainTokensOptions: TokenOption[];
|
|
70
76
|
dstChainOtherTokensOptions: TokenOption[];
|
|
71
|
-
|
|
77
|
+
dstTokenLocked: boolean;
|
|
78
|
+
dstChainLocked?: boolean;
|
|
79
|
+
srcTokenLocked?: boolean;
|
|
80
|
+
srcChainLocked?: boolean;
|
|
72
81
|
dstToken: Token | undefined;
|
|
73
82
|
setDstToken: Dispatch<SetStateAction<Token | undefined>>;
|
|
74
83
|
srcValue: string;
|
|
@@ -102,6 +111,7 @@ type SwapContext = {
|
|
|
102
111
|
tokenAddress: string,
|
|
103
112
|
chainId: string,
|
|
104
113
|
) => Token | undefined;
|
|
114
|
+
bridgeTokensDictionary: BridgeTokensDictionary | null;
|
|
105
115
|
};
|
|
106
116
|
|
|
107
117
|
const functionNotImplemented = () => {
|
|
@@ -109,6 +119,7 @@ const functionNotImplemented = () => {
|
|
|
109
119
|
};
|
|
110
120
|
|
|
111
121
|
const init: SwapContext = {
|
|
122
|
+
bridgeUI: false,
|
|
112
123
|
integrationConfig: {},
|
|
113
124
|
wagmiConfig: {} as Config,
|
|
114
125
|
supportedChains: [],
|
|
@@ -116,19 +127,19 @@ const init: SwapContext = {
|
|
|
116
127
|
overlay: false,
|
|
117
128
|
error: "",
|
|
118
129
|
feeToken: undefined,
|
|
119
|
-
srcChainProvided: false,
|
|
120
130
|
srcChain: undefined,
|
|
121
131
|
srcChainTokensOptions: [],
|
|
122
132
|
srcChainOtherTokensOptions: [],
|
|
123
133
|
srcChainTokensPrices: {},
|
|
124
134
|
dstChainTokensPrices: {},
|
|
125
|
-
dstChainProvided: false,
|
|
126
135
|
dstChain: undefined,
|
|
127
136
|
dstChainTokensOptions: [],
|
|
128
137
|
dstChainOtherTokensOptions: [],
|
|
129
|
-
srcTokenProvided: false,
|
|
130
138
|
srcToken: undefined,
|
|
131
|
-
|
|
139
|
+
dstTokenLocked: false,
|
|
140
|
+
dstChainLocked: false,
|
|
141
|
+
srcTokenLocked: false,
|
|
142
|
+
srcChainLocked: false,
|
|
132
143
|
dstToken: undefined,
|
|
133
144
|
srcValue: "",
|
|
134
145
|
srcValueWei: "",
|
|
@@ -164,6 +175,7 @@ const init: SwapContext = {
|
|
|
164
175
|
quoteRoute: functionNotImplemented,
|
|
165
176
|
refreshBalance: functionNotImplemented,
|
|
166
177
|
findTokenDataByAddressAndChain: functionNotImplemented,
|
|
178
|
+
bridgeTokensDictionary: null,
|
|
167
179
|
};
|
|
168
180
|
|
|
169
181
|
const swapContext = createContext(init);
|
|
@@ -189,22 +201,28 @@ export const SwapProvider = ({
|
|
|
189
201
|
const [infiniteApproval, setInfiniteApproval] = useState(
|
|
190
202
|
init.infiniteApproval,
|
|
191
203
|
);
|
|
192
|
-
const
|
|
193
|
-
() => !!integrationConfig?.
|
|
194
|
-
[integrationConfig?.
|
|
204
|
+
const srcTokenLocked = useMemo(
|
|
205
|
+
() => !!integrationConfig?.srcTokenLocked,
|
|
206
|
+
[integrationConfig?.srcTokenLocked],
|
|
207
|
+
);
|
|
208
|
+
const dstTokenLocked = useMemo(
|
|
209
|
+
() => !!integrationConfig?.dstTokenLocked,
|
|
210
|
+
[integrationConfig?.dstTokenLocked],
|
|
195
211
|
);
|
|
196
|
-
const
|
|
197
|
-
() => !!integrationConfig?.
|
|
198
|
-
[integrationConfig?.
|
|
212
|
+
const srcChainLocked = useMemo(
|
|
213
|
+
() => !!integrationConfig?.srcChainLocked,
|
|
214
|
+
[integrationConfig?.srcChainLocked],
|
|
199
215
|
);
|
|
200
|
-
const
|
|
201
|
-
() => !!integrationConfig?.
|
|
202
|
-
[integrationConfig?.
|
|
216
|
+
const dstChainLocked = useMemo(
|
|
217
|
+
() => !!integrationConfig?.dstChainLocked,
|
|
218
|
+
[integrationConfig?.dstChainLocked],
|
|
203
219
|
);
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
220
|
+
|
|
221
|
+
const bridgeUI = useMemo(
|
|
222
|
+
() => !!integrationConfig.bridge,
|
|
223
|
+
[integrationConfig.bridge],
|
|
207
224
|
);
|
|
225
|
+
|
|
208
226
|
const [slippage, setSlippage] = useState(init.slippage);
|
|
209
227
|
const [srcChain, setSrcChain] = useState(init.srcChain);
|
|
210
228
|
const [dstChain, setDstChain] = useState(init.dstChain);
|
|
@@ -288,14 +306,66 @@ export const SwapProvider = ({
|
|
|
288
306
|
return tempChainToTokenOptionsMap;
|
|
289
307
|
}, [supportedTokens]);
|
|
290
308
|
|
|
309
|
+
const [bridgeTokens, setBridgeTokens] = useState<BridgeToken[]>([]);
|
|
310
|
+
useEffect(() => {
|
|
311
|
+
(async () => {
|
|
312
|
+
const data = await getBridgeTokens();
|
|
313
|
+
setBridgeTokens(data);
|
|
314
|
+
})();
|
|
315
|
+
}, []);
|
|
316
|
+
|
|
317
|
+
const bridgeTokensDictionary = useMemo(() => {
|
|
318
|
+
const result: BridgeTokensDictionary = {};
|
|
319
|
+
|
|
320
|
+
for (const dict of bridgeTokens) {
|
|
321
|
+
const [chainId0, address0] = Object.entries(dict)[0]!;
|
|
322
|
+
const [chainId1, address1] = Object.entries(dict)[1]!;
|
|
323
|
+
if (!result[chainId0]) {
|
|
324
|
+
result[chainId0] = {};
|
|
325
|
+
}
|
|
326
|
+
if (!result[chainId0][address0]) {
|
|
327
|
+
result[chainId0][address0] = {};
|
|
328
|
+
}
|
|
329
|
+
result[chainId0][address0][chainId1] = address1;
|
|
330
|
+
if (!result[chainId1]) {
|
|
331
|
+
result[chainId1] = {};
|
|
332
|
+
}
|
|
333
|
+
if (!result[chainId1][address1]) {
|
|
334
|
+
result[chainId1][address1] = {};
|
|
335
|
+
}
|
|
336
|
+
result[chainId1][address1][chainId0] = address0;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
if (Object.keys(result).length) {
|
|
340
|
+
return result;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return null;
|
|
344
|
+
}, [bridgeTokens]);
|
|
345
|
+
|
|
291
346
|
const getTokenOptions = useCallback(
|
|
292
|
-
(chainId: string, oppositeChainId: string) => {
|
|
347
|
+
(chainId: string | undefined, oppositeChainId: string | undefined) => {
|
|
293
348
|
if (!chainId || !oppositeChainId) {
|
|
294
349
|
return [];
|
|
295
350
|
}
|
|
351
|
+
|
|
352
|
+
if (bridgeTokensDictionary && bridgeUI) {
|
|
353
|
+
if (!chainToTokenOptionsMap[chainId]) {
|
|
354
|
+
return [];
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return chainToTokenOptionsMap[chainId].filter((tokenData) => {
|
|
358
|
+
const supportedTokensAddresses = Object.keys(
|
|
359
|
+
bridgeTokensDictionary[chainId] || {},
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
return supportedTokensAddresses.includes(tokenData.address);
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
296
366
|
return chainToTokenOptionsMap[chainId] || [];
|
|
297
367
|
},
|
|
298
|
-
[chainToTokenOptionsMap],
|
|
368
|
+
[bridgeTokensDictionary, bridgeUI, chainToTokenOptionsMap],
|
|
299
369
|
);
|
|
300
370
|
|
|
301
371
|
const srcTokenBalanceInfo = useMemo(() => {
|
|
@@ -665,9 +735,88 @@ export const SwapProvider = ({
|
|
|
665
735
|
setDstToken(initDstToken);
|
|
666
736
|
}, [integrationConfig, supportedChains]);
|
|
667
737
|
|
|
738
|
+
useEffect(() => {
|
|
739
|
+
if (!bridgeTokensDictionary) {
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
const { source, target } = mapToValidPath({
|
|
744
|
+
source: { chain: srcChain, token: srcToken },
|
|
745
|
+
target: { chain: dstChain, token: dstToken },
|
|
746
|
+
type: bridgeUI ? "BRIDGE" : "SWAP",
|
|
747
|
+
supportedChains,
|
|
748
|
+
bridgeTokensDictionary,
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
if (source.chain?.chainId !== srcChain?.chainId) {
|
|
752
|
+
setSrcChain(source.chain);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
if (target.chain?.chainId !== dstChain?.chainId) {
|
|
756
|
+
setDstChain(target.chain);
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
if (source.token?.address !== srcToken?.address) {
|
|
760
|
+
setSrcToken(source.token);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
if (target.token?.address !== dstToken?.address) {
|
|
764
|
+
setDstToken(target.token);
|
|
765
|
+
}
|
|
766
|
+
}, [
|
|
767
|
+
srcChain,
|
|
768
|
+
srcToken,
|
|
769
|
+
dstChain,
|
|
770
|
+
dstToken,
|
|
771
|
+
bridgeUI,
|
|
772
|
+
supportedChains,
|
|
773
|
+
bridgeTokensDictionary,
|
|
774
|
+
]);
|
|
775
|
+
|
|
776
|
+
useEffect(() => {
|
|
777
|
+
if (integrationConfig.onDstChainChange) {
|
|
778
|
+
integrationConfig.onDstChainChange(dstChain?.chainId);
|
|
779
|
+
} else if (window.xPayOnDstChainChange) {
|
|
780
|
+
window.xPayOnDstChainChange(dstChain?.chainId);
|
|
781
|
+
}
|
|
782
|
+
}, [integrationConfig, dstChain]);
|
|
783
|
+
|
|
784
|
+
useEffect(() => {
|
|
785
|
+
const token = dstToken
|
|
786
|
+
? { address: dstToken.address.toLowerCase(), symbol: dstToken.symbol }
|
|
787
|
+
: undefined;
|
|
788
|
+
|
|
789
|
+
if (integrationConfig.onDstTokenChange) {
|
|
790
|
+
integrationConfig.onDstTokenChange(token);
|
|
791
|
+
} else if (window.xPayOnDstTokenChange) {
|
|
792
|
+
window.xPayOnDstTokenChange(token);
|
|
793
|
+
}
|
|
794
|
+
}, [integrationConfig, dstToken]);
|
|
795
|
+
|
|
796
|
+
useEffect(() => {
|
|
797
|
+
if (integrationConfig.onSrcChainChange) {
|
|
798
|
+
integrationConfig.onSrcChainChange(srcChain?.chainId);
|
|
799
|
+
} else if (window.xPayOnSrcChainChange) {
|
|
800
|
+
window.xPayOnSrcChainChange(srcChain?.chainId);
|
|
801
|
+
}
|
|
802
|
+
}, [integrationConfig, srcChain]);
|
|
803
|
+
|
|
804
|
+
useEffect(() => {
|
|
805
|
+
const token = srcToken
|
|
806
|
+
? { address: srcToken.address.toLowerCase(), symbol: srcToken.symbol }
|
|
807
|
+
: undefined;
|
|
808
|
+
|
|
809
|
+
if (integrationConfig.onSrcTokenChange) {
|
|
810
|
+
integrationConfig.onSrcTokenChange(token);
|
|
811
|
+
} else if (window.xPayOnSrcTokenChange) {
|
|
812
|
+
window.xPayOnSrcTokenChange(token);
|
|
813
|
+
}
|
|
814
|
+
}, [integrationConfig, srcToken]);
|
|
815
|
+
|
|
668
816
|
return (
|
|
669
817
|
<swapContext.Provider
|
|
670
818
|
value={{
|
|
819
|
+
bridgeUI,
|
|
671
820
|
integrationConfig,
|
|
672
821
|
wagmiConfig,
|
|
673
822
|
supportedChains,
|
|
@@ -677,22 +826,18 @@ export const SwapProvider = ({
|
|
|
677
826
|
error,
|
|
678
827
|
setError,
|
|
679
828
|
feeToken,
|
|
680
|
-
srcChainProvided,
|
|
681
829
|
srcChain,
|
|
682
830
|
setSrcChain,
|
|
683
831
|
srcChainTokensOptions,
|
|
684
832
|
srcChainOtherTokensOptions,
|
|
685
833
|
dstChainTokensPrices,
|
|
686
834
|
srcChainTokensPrices,
|
|
687
|
-
dstChainProvided,
|
|
688
835
|
dstChain,
|
|
689
836
|
setDstChain,
|
|
690
837
|
dstChainTokensOptions,
|
|
691
838
|
dstChainOtherTokensOptions,
|
|
692
|
-
srcTokenProvided,
|
|
693
839
|
srcToken,
|
|
694
840
|
setSrcToken,
|
|
695
|
-
dstTokenProvided,
|
|
696
841
|
dstToken,
|
|
697
842
|
setDstToken,
|
|
698
843
|
srcValue,
|
|
@@ -723,6 +868,11 @@ export const SwapProvider = ({
|
|
|
723
868
|
quoteRoute,
|
|
724
869
|
refreshBalance,
|
|
725
870
|
findTokenDataByAddressAndChain,
|
|
871
|
+
srcTokenLocked,
|
|
872
|
+
srcChainLocked,
|
|
873
|
+
dstTokenLocked,
|
|
874
|
+
dstChainLocked,
|
|
875
|
+
bridgeTokensDictionary,
|
|
726
876
|
}}
|
|
727
877
|
>
|
|
728
878
|
{children}
|
package/src/models/TokenData.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Web3Environment } from "./Web3Environment";
|
|
2
1
|
import { BigNumber } from "ethers";
|
|
2
|
+
import { Web3Environment } from "./Web3Environment";
|
|
3
3
|
|
|
4
4
|
export type Chain = {
|
|
5
5
|
ecosystem: string;
|
|
@@ -17,6 +17,8 @@ export type Chain = {
|
|
|
17
17
|
publicRpcUrls: string[];
|
|
18
18
|
privateRpcUrls?: string[];
|
|
19
19
|
scanApiURL?: string;
|
|
20
|
+
defaultDstChain?: string;
|
|
21
|
+
disabledForDestination?: string[];
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
export type Token = {
|