@xswap-link/sdk 0.3.5 → 0.4.1

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 (199) hide show
  1. package/.eslintrc.json +9 -5
  2. package/CHANGELOG.md +16 -0
  3. package/README.md +2 -1
  4. package/dist/index.d.mts +106 -20
  5. package/dist/index.d.ts +106 -20
  6. package/dist/index.global.js +856 -307
  7. package/dist/index.global.js.map +1 -0
  8. package/dist/index.js +105 -3564
  9. package/dist/index.js.map +1 -0
  10. package/dist/index.mjs +105 -3534
  11. package/dist/index.mjs.map +1 -0
  12. package/nodemon.json +1 -1
  13. package/package.json +16 -9
  14. package/postcss.config.js +8 -1
  15. package/src/{components → assets}/icons/ArrowDownIcon.tsx +1 -2
  16. package/src/assets/icons/ArrowDownLongIcon.tsx +12 -0
  17. package/src/{components → assets}/icons/ArrowLeftIcon.tsx +1 -5
  18. package/src/{components → assets}/icons/ArrowRightIcon.tsx +1 -5
  19. package/src/assets/icons/ArrowUpIcon.tsx +12 -0
  20. package/src/{components → assets}/icons/ArrowUpRightIcon.tsx +1 -5
  21. package/src/assets/icons/CashbacklIcon.tsx +28 -0
  22. package/src/{components → assets}/icons/CheckIcon.tsx +1 -5
  23. package/src/assets/icons/ChevronDownIcon.tsx +12 -0
  24. package/src/assets/icons/ChevronUpIcon.tsx +7 -0
  25. package/src/{components → assets}/icons/CircularProgressIcon.tsx +1 -2
  26. package/src/assets/icons/CloseIcon.tsx +15 -0
  27. package/src/{components → assets}/icons/CoinsIcon.tsx +0 -2
  28. package/src/assets/icons/CopyIcon.tsx +15 -0
  29. package/src/assets/icons/DotGreenIcon.tsx +12 -0
  30. package/src/{components → assets}/icons/DownArrorIcon.tsx +0 -2
  31. package/src/{components → assets}/icons/ErrorIcon.tsx +0 -1
  32. package/src/assets/icons/ErrorModalStatusIcon.tsx +31 -0
  33. package/src/assets/icons/HelpIcon.tsx +21 -0
  34. package/src/assets/icons/HistoryGradientBgIcon.tsx +32 -0
  35. package/src/assets/icons/HistoryIcon.tsx +12 -0
  36. package/src/{components → assets}/icons/HourGlassIcon.tsx +1 -5
  37. package/src/assets/icons/Icon.tsx +5 -0
  38. package/src/{components → assets}/icons/InfoIcon.tsx +0 -1
  39. package/src/assets/icons/LinkExternalIcon.tsx +15 -0
  40. package/src/{components → assets}/icons/PercentageIcon.tsx +0 -1
  41. package/src/assets/icons/RankIcon.tsx +28 -0
  42. package/src/assets/icons/SettingsGradientBgIcon.tsx +32 -0
  43. package/src/assets/icons/SettingsIcon.tsx +12 -0
  44. package/src/{components → assets}/icons/SignIcon.tsx +0 -2
  45. package/src/{components → assets}/icons/SuccessIcon.tsx +0 -1
  46. package/src/assets/icons/SuccessModalStatusIcon.tsx +31 -0
  47. package/src/assets/icons/ThumbUpRoundedIcon.tsx +15 -0
  48. package/src/{components → assets}/icons/TimerIcon.tsx +0 -1
  49. package/src/assets/icons/TokensIcon.tsx +16 -0
  50. package/src/assets/icons/WaitingIcon.tsx +15 -0
  51. package/src/{components → assets}/icons/XMarkIcon.tsx +1 -5
  52. package/src/assets/icons/XPowerIcon.tsx +28 -0
  53. package/src/{components → assets}/icons/index.ts +16 -0
  54. package/src/components/Alert/index.tsx +1 -1
  55. package/src/components/Button/index.tsx +57 -0
  56. package/src/components/MessageBar/SnackMessage.tsx +32 -0
  57. package/src/components/MessageBar/index.tsx +44 -0
  58. package/src/components/Modal/index.tsx +52 -0
  59. package/src/components/PoweredBy/index.tsx +12 -0
  60. package/src/components/SafeInput/index.tsx +51 -0
  61. package/src/components/Skeleton/index.tsx +5 -9
  62. package/src/components/Spinner/index.tsx +6 -8
  63. package/src/components/Swap/Header/Controls/index.tsx +57 -0
  64. package/src/components/Swap/Header/index.tsx +16 -0
  65. package/src/components/Swap/HistoryView/index.tsx +34 -0
  66. package/src/components/Swap/SettingsView/Delivery/index.tsx +42 -0
  67. package/src/components/Swap/SettingsView/Slippage/index.tsx +80 -0
  68. package/src/components/Swap/SettingsView/index.tsx +11 -0
  69. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/ArrowIcon.tsx +13 -0
  70. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/Header/index.tsx +37 -0
  71. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/Steps/index.tsx +145 -0
  72. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/SwapPanel/index.tsx +61 -0
  73. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/index.tsx +291 -0
  74. package/src/components/Swap/SwapView/ConfirmationView/TxResult/TokenItem/index.tsx +24 -0
  75. package/src/components/Swap/SwapView/ConfirmationView/TxResult/index.tsx +84 -0
  76. package/src/components/Swap/SwapView/ConfirmationView/index.tsx +17 -0
  77. package/src/components/Swap/SwapView/FeesPanel/DeliveryInfo/index.tsx +25 -0
  78. package/src/components/Swap/SwapView/FeesPanel/Fee/index.tsx +18 -0
  79. package/src/components/Swap/SwapView/FeesPanel/Fees/index.tsx +71 -0
  80. package/src/components/Swap/SwapView/FeesPanel/index.tsx +67 -0
  81. package/src/components/Swap/SwapView/SwapButton/index.tsx +154 -0
  82. package/src/components/Swap/SwapView/SwapPanel/AmountPanel/Balance/index.tsx +23 -0
  83. package/src/components/Swap/SwapView/SwapPanel/AmountPanel/index.tsx +56 -0
  84. package/src/components/Swap/SwapView/SwapPanel/ChainPanel/ChainPicker/ChainItem/index.tsx +70 -0
  85. package/src/components/Swap/SwapView/SwapPanel/ChainPanel/ChainPicker/index.tsx +62 -0
  86. package/src/components/Swap/SwapView/SwapPanel/ChainPanel/index.tsx +74 -0
  87. package/src/components/Swap/SwapView/SwapPanel/MaxPanel/index.tsx +35 -0
  88. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/QuickPickTokenItem/index.tsx +40 -0
  89. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/TokenItem/index.tsx +62 -0
  90. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/TokenPicker/index.tsx +399 -0
  91. package/src/components/Swap/SwapView/SwapPanel/TokenPanel/index.tsx +104 -0
  92. package/src/components/Swap/SwapView/SwapPanel/index.tsx +42 -0
  93. package/src/components/Swap/SwapView/index.tsx +20 -0
  94. package/src/components/Swap/index.tsx +34 -0
  95. package/src/components/TextInput/index.tsx +67 -0
  96. package/src/components/Timer/index.tsx +57 -0
  97. package/src/components/ToggleButton/index.tsx +24 -0
  98. package/src/components/{UnknownTokenLogo/UnknownTokenLogo.tsx → TokenLogo/Unknown/index.tsx} +3 -4
  99. package/src/components/TokenLogo/WithChain/index.tsx +34 -0
  100. package/src/components/TokenLogo/index.tsx +22 -0
  101. package/src/components/Tooltip/index.tsx +108 -0
  102. package/src/components/TxConfigForm/index.tsx +63 -42
  103. package/src/components/TxDataCard/TokenDetails/index.tsx +30 -0
  104. package/src/components/TxDataCard/TxDataCardUI/index.tsx +133 -0
  105. package/src/components/TxDataCard/index.tsx +30 -0
  106. package/src/components/TxStatusButton/index.tsx +64 -108
  107. package/src/components/global.css +115 -4
  108. package/src/components/index.ts +18 -1
  109. package/src/config/fonts.ts +114 -0
  110. package/src/config/global.d.ts +4 -0
  111. package/src/config/init.tsx +35 -31
  112. package/src/constants/crosschainEstimationTimes.ts +52 -0
  113. package/src/constants/index.ts +8 -0
  114. package/src/context/GlobalDataProvider.tsx +165 -0
  115. package/src/context/HistoryProvider.tsx +339 -0
  116. package/src/context/ModalProvider.tsx +47 -0
  117. package/src/context/SwapProvider.tsx +664 -0
  118. package/src/context/TransactionProvider.tsx +86 -0
  119. package/src/context/TxUIWrapper.tsx +388 -0
  120. package/src/context/index.ts +5 -0
  121. package/src/contracts/abi/CustomXSwapRouter.json +953 -0
  122. package/src/contracts/abi/StakingStableAPR.json +1438 -0
  123. package/src/contracts/abi/XSwapRouter.json +1242 -0
  124. package/src/contracts/abi/XSwapTokenFeeDistributor.json +350 -0
  125. package/src/contracts/abi/index.ts +8 -0
  126. package/src/contracts/addresses.ts +24 -6
  127. package/src/fonts/Satoshi-Black.woff2 +0 -0
  128. package/src/fonts/Satoshi-BlackItalic.woff2 +0 -0
  129. package/src/fonts/Satoshi-Bold.woff2 +0 -0
  130. package/src/fonts/Satoshi-BoldItalic.woff2 +0 -0
  131. package/src/fonts/Satoshi-Light.woff2 +0 -0
  132. package/src/fonts/Satoshi-LightItalic.woff2 +0 -0
  133. package/src/fonts/Satoshi-Medium.woff2 +0 -0
  134. package/src/fonts/Satoshi-MediumItalic.woff2 +0 -0
  135. package/src/fonts/Satoshi-Regular.woff2 +0 -0
  136. package/src/fonts/Satoshi-RegularItalic.woff2 +0 -0
  137. package/src/fonts/Satoshi-Variable.woff2 +0 -0
  138. package/src/fonts/Satoshi-VariableItalic.woff2 +0 -0
  139. package/src/hooks/index.ts +5 -0
  140. package/src/hooks/networkManagement/clientToSigner.tsx +17 -0
  141. package/src/hooks/networkManagement/useNetworks.ts +51 -0
  142. package/src/hooks/useBatchQuery.ts +46 -0
  143. package/src/hooks/useDebounce.tsx +28 -0
  144. package/src/hooks/useEvmContractApi.ts +85 -0
  145. package/src/hooks/usePortal.ts +79 -0
  146. package/src/hooks/useXPower.ts +58 -0
  147. package/src/models/Addresses.ts +8 -2
  148. package/src/models/TokenData.ts +13 -0
  149. package/src/models/TransactionHistory.ts +2 -0
  150. package/src/models/TxUIWrapper.ts +51 -0
  151. package/src/models/XSwapConfig.ts +1 -0
  152. package/src/models/index.ts +1 -0
  153. package/src/models/payloads/GetBalancesPayload.ts +3 -0
  154. package/src/models/payloads/GetFinishedLeaderboardQuestsPayload.ts +3 -0
  155. package/src/models/payloads/GetLeaderboardChangePayload.ts +4 -0
  156. package/src/models/payloads/{GetSwapTxPayload.ts → ModalIntegrationPayload.ts} +3 -1
  157. package/src/models/payloads/index.ts +5 -2
  158. package/src/services/api.ts +34 -5
  159. package/src/services/integrations/monitoring.ts +49 -37
  160. package/src/services/integrations/transactions.ts +50 -6
  161. package/src/utils/contracts.ts +29 -0
  162. package/src/utils/index.ts +3 -3
  163. package/src/utils/numbers.ts +14 -0
  164. package/src/utils/parseWeb3Error.ts +7 -3
  165. package/tailwind.config.js +15 -5
  166. package/tsconfig.json +7 -7
  167. package/tsup.config.ts +62 -0
  168. package/xswap.config.ts +1 -0
  169. package/dist/index.css +0 -1
  170. package/src/components/TxConfigForm/BalanceComponent.tsx +0 -52
  171. package/src/components/TxConfigForm/Button.tsx +0 -20
  172. package/src/components/TxConfigForm/ChainListElement.tsx +0 -36
  173. package/src/components/TxConfigForm/ConfirmationAmount.tsx +0 -91
  174. package/src/components/TxConfigForm/ConfirmationView/ErrorView.tsx +0 -38
  175. package/src/components/TxConfigForm/ConfirmationView/SuccessView.tsx +0 -159
  176. package/src/components/TxConfigForm/ConfirmationView/index.tsx +0 -149
  177. package/src/components/TxConfigForm/ConnectWalletPrompt.tsx +0 -21
  178. package/src/components/TxConfigForm/Description.tsx +0 -17
  179. package/src/components/TxConfigForm/ErrorField.tsx +0 -19
  180. package/src/components/TxConfigForm/FeesDetails.tsx +0 -117
  181. package/src/components/TxConfigForm/Form.tsx +0 -574
  182. package/src/components/TxConfigForm/History.tsx +0 -131
  183. package/src/components/TxConfigForm/HistoryCard.tsx +0 -182
  184. package/src/components/TxConfigForm/PoweredBy.tsx +0 -12
  185. package/src/components/TxConfigForm/Settings.tsx +0 -143
  186. package/src/components/TxConfigForm/Summary.tsx +0 -105
  187. package/src/components/TxConfigForm/SwapPanel.tsx +0 -185
  188. package/src/components/TxConfigForm/TokenPicker.tsx +0 -176
  189. package/src/components/TxConfigForm/TopBar.tsx +0 -58
  190. package/src/components/TxConfigForm/UsdPrice.tsx +0 -44
  191. package/src/components/icons/ChevronDownIcon.tsx +0 -15
  192. package/src/components/icons/ChevronUpIcon.tsx +0 -10
  193. package/src/components/icons/CloseIcon.tsx +0 -15
  194. package/src/components/icons/HistoryIcon.tsx +0 -16
  195. package/src/components/icons/SettingsIcon.tsx +0 -16
  196. /package/src/{components → assets}/icons/ChainlinkCCIPIcon.tsx +0 -0
  197. /package/src/{components → assets}/icons/SearchIcon.tsx +0 -0
  198. /package/src/{components → assets}/icons/XSwapBadgeIcon.tsx +0 -0
  199. /package/src/{components → assets}/icons/XSwapLogo.tsx +0 -0
@@ -1,574 +0,0 @@
1
- import "@src/global.css";
2
- import {
3
- FormEvent,
4
- useCallback,
5
- useEffect,
6
- useMemo,
7
- useRef,
8
- useState,
9
- } from "react";
10
- import { ethers } from "ethers";
11
- import { Config, useAccount, useSendTransaction, useSwitchChain } from "wagmi";
12
- import { Chain, Route, Token, TokenBalances, TokenPrices } from "@src/models";
13
- import {
14
- getCustomTokenData,
15
- getPrices,
16
- getRoute,
17
- renderTxStatus,
18
- } from "@src/services";
19
- import { getBalances, safeBigNumberFrom } from "@src/utils";
20
- import {
21
- DEFAULT_REQUEST_ABORT_MSG,
22
- DEFAULT_SOURCE_CHAIN_ID,
23
- ROUTE_TIMEOUT_MS,
24
- } from "@src/constants";
25
- import { TxConfigFormProps } from "@src/components";
26
- import { ADDRESSES } from "@src/contracts";
27
- import { History } from "./History";
28
- import { TopBar } from "./TopBar";
29
- import { Settings } from "./Settings";
30
- import { FeesDetails } from "./FeesDetails";
31
- import { Summary } from "./Summary";
32
- import { SwapPanel } from "./SwapPanel";
33
- import { ErrorField } from "./ErrorField";
34
- import { Description } from "./Description";
35
- import { Button } from "./Button";
36
- import { getChainId, waitForTransactionReceipt } from "wagmi/actions";
37
- import { ConfirmationView } from "./ConfirmationView";
38
- import { ConnectWalletPrompt } from "./ConnectWalletPrompt";
39
-
40
- export const Form = ({
41
- integratorId,
42
- dstChainId,
43
- dstTokenAddr,
44
- customContractCalls,
45
- desc,
46
- supportedChains,
47
- returnTransactions,
48
- dstDisplayTokenAddr,
49
- wagmiConfig,
50
- onSubmit,
51
- onClose,
52
- setBackdropClickDisabled,
53
- }: TxConfigFormProps & {
54
- wagmiConfig: Config;
55
- returnTransactions: boolean;
56
- onSubmit: (route: Route) => void;
57
- onClose: () => void;
58
- setBackdropClickDisabled: (disabled: boolean) => void;
59
- }) => {
60
- const [signer, setSigner] = useState<string | undefined>();
61
- const [dstChain, setDstChain] = useState<Chain>();
62
- const [dstToken, setDstToken] = useState<Token>();
63
- const [dstDisplayToken, setDstDisplayToken] = useState<Token>();
64
- const [srcChain, setSrcChain] = useState<Chain>();
65
- const [srcToken, setSrcToken] = useState<Token>();
66
- const [amount, setAmount] = useState("");
67
- const [paymentToken, setPaymentToken] = useState<Token>();
68
- const [route, setRoute] = useState<Route>();
69
- const [expressChecked, setExpressChecked] = useState(true);
70
- const [historyTabShown, setHistoryTabShown] = useState(false);
71
- const [isGettingRoute, setIsGettingRoute] = useState(false);
72
- const [prices, setPrices] = useState<TokenPrices>();
73
- const [balances, setBalances] = useState<TokenBalances>();
74
- const [settingsShown, setSettingsShown] = useState(false);
75
- const [formError, setFormError] = useState("");
76
- const [slippage, setSlippage] = useState("1.5");
77
- const [feesDetailsShown, setFeesDetailsShown] = useState(false);
78
- const [executingTransactions, setExecutingTransactions] = useState(false);
79
- const [transactionSuccessHash, setTransactionSuccessHash] = useState<
80
- string | undefined
81
- >();
82
-
83
- const [txLoading, setTxLoading] = useState(false);
84
- const [approveTxLoading, setApproveTxLoading] = useState(false);
85
- const [approveTxDone, setApproveTxDone] = useState(false);
86
- const [transactionError, setTransactionError] = useState<string | null>(null);
87
-
88
- const routeAbortController = useRef<AbortController | null>(null);
89
-
90
- // Wagmi hook to execute transactions
91
- const { sendTransaction } = useSendTransaction({ config: wagmiConfig });
92
-
93
- const account = useAccount();
94
- const { switchChainAsync } = useSwitchChain();
95
-
96
- // set signer address
97
- useEffect(() => {
98
- setSigner(account.address);
99
- }, [account.address]);
100
-
101
- // set source chain
102
- useEffect(() => {
103
- const defaultChain = supportedChains.find(
104
- ({ chainId }) => chainId === account.chainId?.toString(),
105
- );
106
- setSrcChain(
107
- defaultChain ??
108
- supportedChains.find(
109
- ({ chainId }) => chainId === DEFAULT_SOURCE_CHAIN_ID,
110
- ),
111
- );
112
- }, [account.chainId]);
113
-
114
- // set destination chain
115
- useEffect(() => {
116
- setDstChain(supportedChains.find((chain) => chain.chainId === dstChainId));
117
- }, [supportedChains, dstChainId]);
118
-
119
- // set destination token
120
- useEffect(() => {
121
- (async () => {
122
- if (!dstChain) {
123
- return;
124
- }
125
-
126
- let dstTokenResult = dstChain?.tokens.find(
127
- (token) => token.address.toLowerCase() === dstTokenAddr.toLowerCase(),
128
- );
129
-
130
- if (!dstTokenResult) {
131
- dstTokenResult = await getCustomTokenData(
132
- dstChain,
133
- dstTokenAddr.toLowerCase(),
134
- );
135
- }
136
-
137
- setDstToken(dstTokenResult);
138
-
139
- if (dstDisplayTokenAddr) {
140
- let dstDisplayTokenResult = dstChain?.tokens.find(
141
- (token) =>
142
- token.address.toLowerCase() === dstDisplayTokenAddr.toLowerCase(),
143
- );
144
-
145
- if (!dstDisplayTokenResult) {
146
- dstDisplayTokenResult = await getCustomTokenData(
147
- dstChain,
148
- dstDisplayTokenAddr.toLowerCase(),
149
- );
150
- }
151
-
152
- setDstDisplayToken(dstDisplayTokenResult);
153
- }
154
- })();
155
- }, [dstChain]);
156
-
157
- // Handle fetching route
158
- useEffect(() => {
159
- if (
160
- !(
161
- integratorId &&
162
- srcChain &&
163
- srcToken &&
164
- dstChain &&
165
- amount &&
166
- paymentToken &&
167
- signer &&
168
- slippage
169
- )
170
- ) {
171
- return;
172
- }
173
-
174
- setFormError("");
175
- const timeout = setTimeout(() => {
176
- setFormError("Getting Route is taking longer than usually");
177
- }, ROUTE_TIMEOUT_MS);
178
- setIsGettingRoute(true);
179
- setFeesDetailsShown(false);
180
- if (!srcToken.decimals)
181
- throw new Error(
182
- `Configuration error: selected token ($${srcToken.symbol} ${srcToken.name}) has unknown decimals param.`,
183
- );
184
-
185
- if (routeAbortController.current) {
186
- routeAbortController.current.abort(DEFAULT_REQUEST_ABORT_MSG);
187
- }
188
- routeAbortController.current = new AbortController();
189
-
190
- getRoute(
191
- {
192
- integratorId,
193
- fromAmount: ethers.utils
194
- .parseUnits(amount, srcToken.decimals)
195
- .toString(),
196
- fromAddress: signer || ADDRESSES[srcChain.chainId]!.FeeCollector,
197
- fromChain: srcChain.chainId,
198
- fromToken: srcToken.address,
199
- toAddress: signer || ADDRESSES[dstChain.chainId]!.FeeCollector,
200
- toChain: dstChainId,
201
- toToken: dstTokenAddr,
202
- paymentToken: paymentToken.address,
203
- slippage: Number(slippage),
204
- expressDelivery: expressChecked,
205
- customContractCalls,
206
- },
207
- routeAbortController.current.signal,
208
- )
209
- .then((response) => {
210
- setRoute(response);
211
- setFormError("");
212
- setIsGettingRoute(false);
213
- routeAbortController.current = null;
214
- })
215
- .catch((err) => {
216
- if (err !== DEFAULT_REQUEST_ABORT_MSG) {
217
- setFormError(err.message);
218
- }
219
- })
220
- .finally(() => {
221
- clearTimeout(timeout);
222
- });
223
- }, [
224
- amount,
225
- signer,
226
- srcChain,
227
- srcToken,
228
- paymentToken,
229
- slippage,
230
- expressChecked,
231
- ]);
232
-
233
- // Set fee payment token
234
- useEffect(() => {
235
- if (srcChain) {
236
- setPaymentToken(
237
- srcChain.tokens.find(
238
- (token) =>
239
- token.address.toLowerCase() ===
240
- ethers.constants.AddressZero.toLowerCase(),
241
- ),
242
- );
243
- }
244
- }, [srcChain]);
245
-
246
- // Clear state on source token change
247
- useEffect(() => {
248
- setAmount("");
249
- setFormError("");
250
- setIsGettingRoute(false);
251
- setRoute(undefined);
252
- }, [srcToken]);
253
-
254
- // Clear state on source chain change
255
- useEffect(() => {
256
- setSrcToken(srcChain?.tokens[0]);
257
- setAmount("");
258
- setIsGettingRoute(false);
259
- setRoute(undefined);
260
- }, [srcChain]);
261
-
262
- // Fetch token prices on source chain
263
- useEffect(() => {
264
- if (srcChain) {
265
- getPrices({ chainId: srcChain.chainId, currency: "USD" }).then((prices) =>
266
- setPrices(prices),
267
- );
268
- }
269
- }, [srcChain]);
270
-
271
- // Fetch token balances on source chain
272
- useEffect(() => {
273
- if (srcChain && signer) {
274
- getBalances(srcChain, signer).then((balances) => setBalances(balances));
275
- }
276
- }, [srcChain, signer]);
277
-
278
- // Disable backdrop clicks when executing transactions
279
- useEffect(() => {
280
- setBackdropClickDisabled(executingTransactions);
281
- }, [executingTransactions]);
282
-
283
- // Execute the transactions received from the xPay.
284
- const triggerTx = useCallback(async () => {
285
- if (!route) {
286
- return;
287
- }
288
- setExecutingTransactions(true);
289
- setBackdropClickDisabled(true);
290
- setTransactionError(null);
291
-
292
- // Optional approve for ERC20 tokens.
293
- if (route.transactions.approve) {
294
- setApproveTxDone(false);
295
-
296
- const { to, data } = route.transactions.approve;
297
- sendTransaction(
298
- {
299
- to,
300
- data,
301
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
302
- } as any,
303
- {
304
- onSuccess: async (hash) => {
305
- setApproveTxLoading(true);
306
- const chainId = getChainId(wagmiConfig);
307
- await waitForTransactionReceipt(wagmiConfig, {
308
- chainId,
309
- hash,
310
- });
311
- setApproveTxLoading(false);
312
- setApproveTxDone(true);
313
- await swap(route);
314
- },
315
- onError: (error) => {
316
- setTransactionError(`Approval failed: ${error.message}`);
317
- setApproveTxLoading(false);
318
- setBackdropClickDisabled(false);
319
- },
320
- },
321
- );
322
- } else {
323
- await swap(route);
324
- }
325
- }, [
326
- route,
327
- signer,
328
- srcChain,
329
- srcToken,
330
- paymentToken,
331
- slippage,
332
- expressChecked,
333
- amount,
334
- ]);
335
-
336
- // Sign and send the swap transaction
337
- const swap = useCallback(
338
- async (route: Route) => {
339
- const { to, value, data } = route.transactions.swap;
340
- sendTransaction(
341
- {
342
- to,
343
- value: BigInt(value),
344
- data,
345
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
346
- } as any,
347
- {
348
- onSuccess: async (hash) => {
349
- setTxLoading(true);
350
- // Open the transaction monitor popup to inform user about the tx status
351
- const chainId = getChainId(wagmiConfig);
352
- await waitForTransactionReceipt(wagmiConfig, {
353
- chainId,
354
- hash,
355
- });
356
- setTxLoading(false);
357
- if (srcChain?.chainId !== dstChain?.chainId) {
358
- renderTxStatus(chainId.toString(), hash);
359
- }
360
- setTransactionSuccessHash(hash);
361
- },
362
- onError: (error) => {
363
- setBackdropClickDisabled(false);
364
- setTransactionError(`Transaction failed: ${error.message}`);
365
- },
366
- },
367
- );
368
- },
369
- [route, signer, srcChain, srcToken, paymentToken, slippage, expressChecked],
370
- );
371
-
372
- // Handle form submit
373
- const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
374
- event.preventDefault();
375
- if (!route) {
376
- return;
377
- }
378
-
379
- if (returnTransactions) {
380
- onSubmit(route);
381
- return;
382
- }
383
-
384
- triggerTx();
385
- };
386
-
387
- const handleSwitchChain = async () => {
388
- await switchChainAsync({ chainId: Number(srcChain?.chainId) });
389
- };
390
-
391
- // provides data for the main button
392
- const swapButton: { text: string; fn: () => void; disabled: boolean } =
393
- useMemo(() => {
394
- if (transactionError) {
395
- return {
396
- text: transactionError,
397
- fn: () => {},
398
- disabled: true,
399
- };
400
- }
401
-
402
- if (!signer) {
403
- return {
404
- text: "Connect wallet",
405
- fn: () => {},
406
- disabled: false,
407
- };
408
- }
409
-
410
- if (
411
- signer &&
412
- srcChain &&
413
- srcChain.chainId !== account.chainId?.toString()
414
- ) {
415
- return {
416
- text: "Switch chain",
417
- fn: handleSwitchChain,
418
-
419
- disabled: false,
420
- };
421
- }
422
-
423
- if (!amount) {
424
- return {
425
- text: `Enter token amount`,
426
- fn: () => {},
427
- disabled: true,
428
- };
429
- }
430
-
431
- if (
432
- amount &&
433
- balances &&
434
- srcToken &&
435
- srcToken.decimals &&
436
- balances[srcToken?.address] !== undefined &&
437
- !ethers.utils
438
- .parseUnits(amount, srcToken.decimals)
439
- .lt(balances[srcToken?.address] || "0")
440
- ) {
441
- return {
442
- text: "Insufficient balance",
443
- fn: () => {},
444
- disabled: true,
445
- };
446
- }
447
-
448
- if (!route) {
449
- return {
450
- text: `Loading route`,
451
- fn: () => {},
452
- disabled: true,
453
- };
454
- }
455
-
456
- return {
457
- text: "Submit",
458
- fn: () => {},
459
- disabled: false,
460
- };
461
- }, [
462
- account,
463
- srcToken,
464
- srcChain,
465
- amount,
466
- balances,
467
- signer,
468
- transactionError,
469
- route,
470
- ]);
471
-
472
- // check if the express delivery will be executed
473
- const isExpressDelivery = useMemo(() => {
474
- const expressDeliveryFee =
475
- !route?.xSwapFees || !route?.xSwapFees.expressDeliveryFee
476
- ? safeBigNumberFrom("0")
477
- : safeBigNumberFrom(route?.xSwapFees.expressDeliveryFee);
478
- return expressDeliveryFee.gt("0");
479
- }, [route]);
480
-
481
- return (
482
- <>
483
- {!signer ? (
484
- <ConnectWalletPrompt onClose={onClose} />
485
- ) : executingTransactions ? (
486
- <ConfirmationView
487
- txError={transactionError}
488
- onClose={onClose}
489
- txSuccessHash={transactionSuccessHash}
490
- srcChain={srcChain}
491
- dstChain={dstChain}
492
- isExpressDelivery={isExpressDelivery}
493
- srcToken={srcToken}
494
- amount={amount}
495
- dstDisplayToken={dstDisplayToken}
496
- dstToken={dstToken}
497
- route={route}
498
- supportedChains={supportedChains}
499
- approveTxLoading={approveTxLoading}
500
- approveTxDone={approveTxDone}
501
- txLoading={txLoading}
502
- />
503
- ) : (
504
- // XPay form
505
- <form
506
- className="xpay-flex xpay-flex-col xpay-gap-2 xpay-z-10 xpay-my-0 p-2 md:xpay-p-4 xpay-rounded-3xl xpay-overflow-hidden xpay-font-light sm:xpay-w-x_desktop"
507
- onSubmit={handleSubmit}
508
- >
509
- <TopBar
510
- signer={signer}
511
- historyTabShown={historyTabShown}
512
- setHistoryTabShown={setHistoryTabShown}
513
- setSettingsShown={setSettingsShown}
514
- onClose={onClose}
515
- />
516
- {settingsShown && (
517
- <Settings
518
- expressChecked={expressChecked}
519
- setExpressChecked={setExpressChecked}
520
- setSettingsShown={setSettingsShown}
521
- slippage={slippage}
522
- setSlippage={setSlippage}
523
- />
524
- )}
525
- {historyTabShown ? (
526
- <History signer={signer} supportedChains={supportedChains} />
527
- ) : (
528
- <div className="xpay-flex xpay-flex-col xpay-gap-2">
529
- <SwapPanel
530
- amount={amount}
531
- setAmount={setAmount}
532
- srcToken={srcToken}
533
- setSrcToken={setSrcToken}
534
- srcChain={srcChain}
535
- signer={signer}
536
- balances={balances}
537
- prices={prices}
538
- supportedChains={supportedChains}
539
- setSrcChain={setSrcChain}
540
- />
541
- <Summary
542
- isGettingRoute={isGettingRoute}
543
- route={route}
544
- dstToken={dstDisplayToken ? dstDisplayToken : dstToken}
545
- dstChain={dstChain}
546
- />
547
- {desc && <Description description={desc} />}
548
-
549
- <FeesDetails
550
- route={route}
551
- isGettingRoute={isGettingRoute}
552
- paymentToken={paymentToken}
553
- dstToken={dstToken}
554
- slippage={slippage}
555
- feesDetailsShown={feesDetailsShown}
556
- setFeesDetailsShown={setFeesDetailsShown}
557
- isExpressDelivery={isExpressDelivery}
558
- />
559
- {formError.length > 0 && <ErrorField error={formError} />}
560
-
561
- <Button
562
- type="submit"
563
- disabled={swapButton.disabled}
564
- onClick={swapButton.fn}
565
- >
566
- {swapButton.text}
567
- </Button>
568
- </div>
569
- )}
570
- </form>
571
- )}
572
- </>
573
- );
574
- };
@@ -1,131 +0,0 @@
1
- import { Transaction, TransactionStatus, Chain } from "@src/models";
2
- import React, { FC, useCallback, useEffect, useState } from "react";
3
- import { getHistory } from "@src/services";
4
- import { DELIVERY_TIME, EXPRESS_DELIVERY_TIME } from "@src/constants";
5
- import BigNumberJS from "bignumber.js";
6
- import { HistoryCard } from "./HistoryCard";
7
- import { CircularProgressIcon } from "../icons";
8
-
9
- interface Props {
10
- signer: string | undefined;
11
- supportedChains: Chain[];
12
- }
13
-
14
- export const History: FC<Props> = ({ signer, supportedChains }) => {
15
- const [fetchedHistory, setFetchedHistory] = useState<Transaction[]>();
16
- const [historyLoadedOnce, setHistoryLoadedOnce] = useState(false);
17
-
18
- const fetchHistory = useCallback(async () => {
19
- if (signer) {
20
- const downloadedHistory = await getHistory({ walletAddress: signer });
21
- const fetchedTransactions: Transaction[] = [];
22
- if (downloadedHistory) {
23
- for (const entry of downloadedHistory.history) {
24
- let status: TransactionStatus = "IN_PROGRESS";
25
-
26
- // single chain tx
27
- if (!entry.source) {
28
- continue;
29
- }
30
-
31
- if (entry.failed) {
32
- status = "REVERTED";
33
- }
34
- if (!!entry.target) {
35
- status = "DONE";
36
- }
37
-
38
- if (entry.transferType === "SINGLE_CHAIN") {
39
- if (!entry.target) {
40
- continue;
41
- }
42
-
43
- const blockTimestampMs = new Date(entry.target.blockTime).getTime();
44
- const estimatedDeliveryTimestamp = blockTimestampMs / 1000;
45
-
46
- fetchedTransactions.push({
47
- hash: entry.target.transactionHash,
48
- timestamp: blockTimestampMs / 1000,
49
- sourceChainId: entry.target.blockchainId,
50
- targetChainId: entry.target.blockchainId,
51
- amountWei: entry.source.tokenAmount,
52
- tokenAddress: entry.source.tokenAddress,
53
- tokenOutAddress: entry.target?.tokenAmount,
54
- tokenOutAmount: entry.target?.tokenAmount,
55
- estimatedDeliveryTimestamp,
56
- status,
57
- });
58
-
59
- continue;
60
- }
61
-
62
- const blockTimestampMs = new Date(entry.source.blockTime).getTime();
63
- const estimatedDeliveryTimestamp = new BigNumberJS(
64
- entry.source.valueForInstantCcipRecieve,
65
- ).gt(0)
66
- ? blockTimestampMs + EXPRESS_DELIVERY_TIME
67
- : blockTimestampMs + DELIVERY_TIME;
68
-
69
- fetchedTransactions.push({
70
- hash: entry.source.transactionHash,
71
- timestamp: blockTimestampMs / 1000,
72
- sourceChainId: entry.source.blockchainId,
73
- targetChainId: entry.source.targetBlockchainId,
74
- amountWei: entry.source.tokenAmount,
75
- tokenAddress: entry.source.tokenAddress,
76
- tokenOutAddress:
77
- entry.target?.tokenAddress || entry.source.tokenOutAddress,
78
- tokenOutAmount:
79
- entry.target?.tokenAmount || entry.source.estimatedAmountOut,
80
- estimatedDeliveryTimestamp,
81
- status,
82
- });
83
- }
84
-
85
- setFetchedHistory(
86
- fetchedTransactions.sort((a, b) => b.timestamp - a.timestamp),
87
- );
88
- setHistoryLoadedOnce(true);
89
- }
90
- }
91
- }, [signer, getHistory]);
92
-
93
- useEffect(() => {
94
- if (!historyLoadedOnce) fetchHistory();
95
- const timer = setInterval(() => {
96
- fetchHistory();
97
- }, 60000);
98
- return () => clearInterval(timer);
99
- }, [signer, fetchHistory, getHistory, historyLoadedOnce]);
100
-
101
- if (!signer)
102
- return (
103
- <div className="xpay-flex xpay-items-center xpay-justify-center xpay-w-full xpay-h-[30vh]">
104
- Connect a wallet to browse history
105
- </div>
106
- );
107
-
108
- return (
109
- <div className="xpay-flex xpay-items-center xpay-justify-center xpay-w-full">
110
- <div className="xpay-w-full xpay-h-96 xpay-overflow-scroll xpay-overflow-x-hidden">
111
- {fetchedHistory?.length === 0 && historyLoadedOnce && (
112
- <div className="xpay-w-full xpay-text-center xpay-py-4 xpay-px-0 xpay-text-[rgb(158,158,158)]">
113
- Your history is empty...
114
- </div>
115
- )}
116
- {!fetchedHistory && !historyLoadedOnce && (
117
- <div className="xpay-flex xpay-w-full xpay-h-full xpay-items-center xpay-justify-center">
118
- <CircularProgressIcon />
119
- </div>
120
- )}
121
- {fetchedHistory?.map((transaction, index) => (
122
- <HistoryCard
123
- key={index}
124
- transaction={transaction}
125
- supportedChains={supportedChains}
126
- />
127
- ))}
128
- </div>
129
- </div>
130
- );
131
- };