@xswap-link/sdk 0.3.5 → 0.4.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.
Files changed (199) hide show
  1. package/.eslintrc.json +9 -5
  2. package/CHANGELOG.md +10 -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 +963 -164
  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 +61 -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
@@ -0,0 +1,79 @@
1
+ import { useEffect, useRef } from "react";
2
+
3
+ /**
4
+ * Creates DOM element to be used as React root.
5
+ */
6
+ function createRootElement(id: string): HTMLElement {
7
+ const rootContainer = document.createElement("div");
8
+ rootContainer.setAttribute("id", id);
9
+ return rootContainer;
10
+ }
11
+
12
+ /**
13
+ * Appends element as last child of body.
14
+ */
15
+ function addRootElement(rootElem: Element): void {
16
+ document.body.insertBefore(
17
+ rootElem,
18
+ document.body.lastElementChild!.nextElementSibling,
19
+ );
20
+ }
21
+
22
+ /**
23
+ * Hook to create a React Portal.
24
+ * Automatically handles creating and tearing-down the root elements (no SRR
25
+ * makes this trivial), so there is no need to ensure the parent target already
26
+ * exists.
27
+ * @example
28
+ * const target = usePortal(id, [id]);
29
+ * return createPortal(children, target);
30
+ * @param {string} id The id of the target container, e.g 'modal' or 'spotlight'
31
+ * @returns {HTMLElement} The DOM node to use as the Portal target.
32
+ */
33
+ export function usePortal(id: string): HTMLElement {
34
+ const rootElemRef = useRef<HTMLElement | null>(null);
35
+
36
+ useEffect(
37
+ function setupElement() {
38
+ // Look for existing target dom element to append to
39
+ const existingParent = document.querySelector(`#${id}`);
40
+ // Parent is either a new root or the existing dom element
41
+ const parentElem = existingParent || createRootElement(id);
42
+
43
+ // If there is no existing DOM element, add a new one.
44
+ if (!existingParent) {
45
+ addRootElement(parentElem);
46
+ }
47
+
48
+ // Add the detached element to the parent
49
+ parentElem.appendChild(rootElemRef.current!);
50
+
51
+ return function removeElement() {
52
+ rootElemRef.current!.remove();
53
+ if (!parentElem.childElementCount) {
54
+ parentElem.remove();
55
+ }
56
+ };
57
+ },
58
+ [id],
59
+ );
60
+
61
+ /**
62
+ * It's important we evaluate this lazily:
63
+ * - We need first render to contain the DOM element, so it shouldn't happen
64
+ * in useEffect. We would normally put this in the constructor().
65
+ * - We can't do 'const rootElemRef = useRef(document.createElement('div))',
66
+ * since this will run every single render (that's a lot).
67
+ * - We want the ref to consistently point to the same DOM element and only
68
+ * ever run once.
69
+ * @link https://reactjs.org/docs/hooks-faq.html#how-to-create-expensive-objects-lazily
70
+ */
71
+ function getRootElem(): HTMLElement {
72
+ if (!rootElemRef.current) {
73
+ rootElemRef.current = document.createElement("div");
74
+ }
75
+ return rootElemRef.current;
76
+ }
77
+
78
+ return getRootElem();
79
+ }
@@ -0,0 +1,58 @@
1
+ import { ADDRESSES, StakingStableAPRAbi } from "@src/contracts";
2
+ import { useBatchQuery } from "./useBatchQuery";
3
+ import { BigNumber, ethers } from "ethers";
4
+ import { useCallback } from "react";
5
+
6
+ const iface = new ethers.utils.Interface(StakingStableAPRAbi);
7
+
8
+ export const useXPower = (chainId: string) => {
9
+ const { batchQuery } = useBatchQuery();
10
+
11
+ return {
12
+ getXPower: useCallback(
13
+ async (address: string) => {
14
+ if (
15
+ !ADDRESSES[chainId]?.StakingCosmicCadets ||
16
+ !ADDRESSES[chainId]?.StakingSolarDivision ||
17
+ !ADDRESSES[chainId]?.StakingIntergalacticCommand
18
+ ) {
19
+ return "0";
20
+ }
21
+
22
+ const stakingAddresses: string[] = [
23
+ ADDRESSES[chainId]?.StakingCosmicCadets,
24
+ ADDRESSES[chainId]?.StakingSolarDivision,
25
+ ADDRESSES[chainId]?.StakingIntergalacticCommand,
26
+ ];
27
+
28
+ const calldata = iface.encodeFunctionData("getStaker", [address]);
29
+ const responses = await batchQuery(
30
+ chainId,
31
+ stakingAddresses,
32
+ stakingAddresses.map(() => calldata),
33
+ );
34
+ if (responses) {
35
+ return responses
36
+ .map(
37
+ (stakerResponse) =>
38
+ ethers.utils.defaultAbiCoder.decode(
39
+ [
40
+ "address",
41
+ "uint256",
42
+ "uint256",
43
+ "uint256",
44
+ "uint256",
45
+ "uint256",
46
+ ],
47
+ stakerResponse,
48
+ )[1],
49
+ )
50
+ .reduce((prev, curr) => prev.add(curr), BigNumber.from(0))
51
+ .toString();
52
+ }
53
+ return "0";
54
+ },
55
+ [batchQuery, chainId],
56
+ ),
57
+ };
58
+ };
@@ -2,12 +2,18 @@ export type Addresses = {
2
2
  [chainId: string]: Contracts;
3
3
  };
4
4
 
5
- export type Contracts = {
5
+ export type Contracts = Partial<{
6
6
  [contractName in ContractName]: string;
7
- };
7
+ }>;
8
8
 
9
9
  export enum ContractName {
10
+ USDC = "USDC",
10
11
  BatchQuery = "BatchQuery",
12
+ CustomXSwapRouter = "CustomXSwapRouter",
11
13
  FeeCollector = "FeeCollector",
14
+ StakingCosmicCadets = "StakingCosmicCadets",
15
+ StakingSolarDivision = "StakingSolarDivision",
16
+ StakingIntergalacticCommand = "StakingIntergalacticCommand",
12
17
  XSwapRouter = "XSwapRouter",
18
+ XSwapToken = "XSwapToken",
13
19
  }
@@ -43,3 +43,16 @@ export type TokenPrices = {
43
43
  export type TokenBalances = {
44
44
  [tokenAddress: string]: BigNumber | undefined;
45
45
  };
46
+
47
+ export type TokenOption = Token & {
48
+ chainId: string;
49
+ disabled?: boolean;
50
+ balance?: BigNumber;
51
+ };
52
+
53
+ export type ImportedTokenData = {
54
+ address: string;
55
+ symbol: string;
56
+ name: string;
57
+ decimals: number;
58
+ };
@@ -8,6 +8,7 @@ export type HistoryTransaction = {
8
8
  transferId: string;
9
9
  transferType: TransferType;
10
10
  walletAddress: string;
11
+ messageId: string;
11
12
  // ExecutorRunFailed
12
13
  failed: boolean;
13
14
  // MessageSent
@@ -41,6 +42,7 @@ export type TransactionStatus =
41
42
  | "NOT_FOUND";
42
43
 
43
44
  export type Transaction = {
45
+ messageId?: string;
44
46
  hash: string;
45
47
  timestamp: number;
46
48
  sourceChainId: string;
@@ -0,0 +1,51 @@
1
+ import { TransactionResponse } from "@ethersproject/providers";
2
+ import { EvmHandlers } from "@src/context";
3
+ import { Ecosystem } from "@src/models";
4
+ import { Dispatch, SetStateAction } from "react";
5
+
6
+ export type EnqueueTxProps = {
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ executeTransaction: () => Promise<TransactionResponse> | undefined;
9
+ txStatus: TxStatus;
10
+ txMsg?: string;
11
+ handlers?: EvmHandlers;
12
+ network?: Ecosystem;
13
+ showDefaultSuccessMessage?: boolean;
14
+ };
15
+
16
+ export type TxUIWrapperState = {
17
+ enqueueTransaction: (props: EnqueueTxProps) => number;
18
+ closeTransactionModal: (nonce: number) => void;
19
+ isTxModalOpen: boolean;
20
+ setTxModalOpen: Dispatch<SetStateAction<boolean>>;
21
+ loading: boolean;
22
+ txStatus: TxStatus;
23
+ setTxStatus: Dispatch<SetStateAction<TxStatus>>;
24
+ txExplorerUrl: string;
25
+ txHash: string;
26
+ txError: string;
27
+ txMsg: string;
28
+ setTxMsg: Dispatch<SetStateAction<string>>;
29
+ setTxError: Dispatch<SetStateAction<string>>;
30
+ txNeedsApproval: boolean;
31
+ setTxNeedsApproval: Dispatch<SetStateAction<boolean>>;
32
+ };
33
+
34
+ /**
35
+ * make sure there's always appropriate CONFIRMATION status following the SIGNING one
36
+ * see setTxStatus((prevStatus) => prevStatus + 1) at TxUIWrapper.tsx -> addUILogicToHandlersEVM
37
+ */
38
+ export enum TxStatus {
39
+ SWAP_INIT,
40
+ SIGNING_APPROVAL,
41
+ CONFIRMING_APPROVAL,
42
+ SIGNING_TX,
43
+ CONFIRMING_TX,
44
+ COMPLETED,
45
+ }
46
+
47
+ export type TxStats = {
48
+ points?: string;
49
+ rank?: string;
50
+ cashback?: string;
51
+ };
@@ -1,3 +1,4 @@
1
1
  export type XSwapConfig = {
2
2
  apiUrl: string;
3
+ localCss: boolean;
3
4
  };
@@ -16,3 +16,4 @@ export * from "./Web3Environment";
16
16
  export * from "./XSwapCallType";
17
17
  export * from "./Referral";
18
18
  export * from "./TransactionHistory";
19
+ export * from "./TxUIWrapper";
@@ -0,0 +1,3 @@
1
+ export type GetTokenBalancesPayload = {
2
+ walletAddress: string;
3
+ };
@@ -0,0 +1,3 @@
1
+ export type GetFinishedLeaderboardQuestsPayload = {
2
+ walletAddress: string;
3
+ };
@@ -0,0 +1,4 @@
1
+ export type GetLeaderboardChangePayload = {
2
+ walletAddress: string;
3
+ additionalPoints: number;
4
+ };
@@ -1,9 +1,11 @@
1
1
  import { ContractCall } from "@src/models";
2
2
 
3
- export type GetSwapTxPayload = {
3
+ export type ModalIntegrationPayload = {
4
4
  integratorId: string;
5
5
  dstChain: string;
6
6
  dstToken: string;
7
+ srcChain?: string;
8
+ srcToken?: string;
7
9
  customContractCalls?: ContractCall[];
8
10
  desc?: string;
9
11
  returnTransactions?: boolean;
@@ -1,4 +1,7 @@
1
- export * from "./GetRoutePayload";
2
1
  export * from "./AddReferralPayload";
3
- export * from "./GetSwapTxPayload";
2
+ export * from "./GetBalancesPayload";
3
+ export * from "./GetFinishedLeaderboardQuestsPayload";
4
+ export * from "./GetLeaderboardChangePayload";
4
5
  export * from "./GetPricesPayload";
6
+ export * from "./GetRoutePayload";
7
+ export * from "./ModalIntegrationPayload";
@@ -1,10 +1,12 @@
1
1
  import xSwapConfig from "../../xswap.config";
2
2
  import {
3
- BridgeToken,
4
3
  Chain,
5
4
  Ecosystem,
5
+ GetFinishedLeaderboardQuestsPayload,
6
+ GetLeaderboardChangePayload,
6
7
  GetPricesPayload,
7
8
  GetRoutePayload,
9
+ GetTokenBalancesPayload,
8
10
  Route,
9
11
  Token,
10
12
  TokenPrices,
@@ -97,10 +99,6 @@ export async function getTokens(
97
99
  );
98
100
  }
99
101
 
100
- export async function getBridgeTokens(): Promise<BridgeToken[]> {
101
- return _sendRequest<BridgeToken[]>(`/bridgeTokens`);
102
- }
103
-
104
102
  export async function getHistory(payload: { walletAddress: string }) {
105
103
  return await _sendRequest<TransactionHistory>(
106
104
  `/history?${new URLSearchParams({
@@ -117,6 +115,15 @@ export async function getPrices(payload: GetPricesPayload) {
117
115
  );
118
116
  }
119
117
 
118
+ export async function getBalances(payload: GetTokenBalancesPayload) {
119
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
120
+ return _sendRequest<any>(
121
+ `/tokenBalances?${new URLSearchParams({
122
+ data: JSON.stringify(payload),
123
+ })}`,
124
+ );
125
+ }
126
+
120
127
  export async function getTxStatus(payload: { transferId: string }) {
121
128
  return await _sendRequest<{ status: TransactionStatus }>(
122
129
  `/getTxStatus?${new URLSearchParams({
@@ -124,3 +131,25 @@ export async function getTxStatus(payload: { transferId: string }) {
124
131
  })}`,
125
132
  );
126
133
  }
134
+
135
+ export async function getLeaderboardChange(
136
+ payload: GetLeaderboardChangePayload,
137
+ ) {
138
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
139
+ return _sendRequest<any>(
140
+ `/leaderboardChange?${new URLSearchParams({
141
+ data: JSON.stringify(payload),
142
+ })}`,
143
+ );
144
+ }
145
+
146
+ export async function getFinishedLeaderboardQuests(
147
+ payload: GetFinishedLeaderboardQuestsPayload,
148
+ ) {
149
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
150
+ return _sendRequest<any>(
151
+ `/getFinishedLeaderboardQuests?${new URLSearchParams({
152
+ data: JSON.stringify(payload),
153
+ })}`,
154
+ );
155
+ }
@@ -1,9 +1,7 @@
1
- import { Chain, MonitoredTransaction, Web3Environment } from "@src/models";
1
+ import { Chain, Token, Transaction, Web3Environment } from "@src/models";
2
2
  import { getChains, getTxStatus } from "@src/services";
3
3
  import { ethers } from "ethers";
4
- import { weiToHumanReadable } from "@src/utils";
5
4
  import {
6
- CCIP_EXPLORER,
7
5
  MSG_RECEIVED_EVENT_ABI,
8
6
  MSG_RECEIVED_EVENT_SIG,
9
7
  MSG_SENT_EVENT_ABI,
@@ -23,9 +21,10 @@ import { getCustomTokenData } from "../blockchain";
23
21
  export const renderTxStatus = async (
24
22
  txChainId: string,
25
23
  txHash: string,
24
+ dstTokenAddress?: string,
25
+ dstTokenAmount?: string,
26
26
  ): Promise<void> => {
27
27
  const txReceipt = await getTxReceipt(txChainId, txHash);
28
-
29
28
  const supportedChains: Chain[] = (await getChains()).filter(
30
29
  ({ web3Environment, swapSupported }) =>
31
30
  web3Environment === Web3Environment.MAINNET && swapSupported,
@@ -50,6 +49,9 @@ export const renderTxStatus = async (
50
49
  `No transaction event arguments found for chain ${txChainId} tx ${txHash}`,
51
50
  );
52
51
  }
52
+
53
+ const MessageSentEventArgs = decodedMessageSentEvent.args;
54
+
53
55
  const srcChain = supportedChains.find(
54
56
  (chain) => chain.chainId === txChainId.toString(),
55
57
  );
@@ -57,20 +59,20 @@ export const renderTxStatus = async (
57
59
  throw new Error(`Unknown src chain ${txChainId}`);
58
60
  }
59
61
 
60
- const tokenAddress = decodedMessageSentEvent.args?.token.toString();
62
+ const srcTokenAddress = MessageSentEventArgs?.token.toString().toLowerCase();
61
63
 
62
64
  let srcToken = srcChain.tokens.find(
63
- (token) => token.address === decodedMessageSentEvent.args?.token.toString(),
65
+ (token) => token.address === srcTokenAddress,
64
66
  );
65
67
 
66
68
  if (!srcToken) {
67
- srcToken = await getCustomTokenData(srcChain, tokenAddress);
69
+ srcToken = await getCustomTokenData(srcChain, srcTokenAddress);
68
70
  }
69
71
 
70
72
  const dstChain = supportedChains.find(
71
73
  (chain) =>
72
74
  chain.ccipChainId ===
73
- decodedMessageSentEvent.args?.destinationChainSelector?.toString(),
75
+ MessageSentEventArgs?.destinationChainSelector?.toString(),
74
76
  );
75
77
 
76
78
  const dstChainId = dstChain?.chainId;
@@ -79,26 +81,36 @@ export const renderTxStatus = async (
79
81
  throw new Error(`Unknown destination chain!`);
80
82
  }
81
83
 
82
- const tokenAmount = weiToHumanReadable({
83
- amount: decodedMessageSentEvent.args?.tokenAmount.toString(),
84
- decimals: srcToken?.decimals || 18,
85
- precisionFractionalPlaces: 4,
86
- });
84
+ let dstToken: Token | undefined = undefined;
85
+ if (dstTokenAddress) {
86
+ dstToken = dstChain.tokens.find(
87
+ (token) => token.address === dstTokenAddress.toLowerCase(),
88
+ );
89
+ }
87
90
 
88
- const transaction: MonitoredTransaction = {
89
- txHash: txHash,
90
- srcChain: srcChain.displayName,
91
- srcChainImage: srcChain.image,
92
- dstChain: dstChain.displayName,
93
- dstChainImage: dstChain.image,
94
- srcToken: srcToken?.symbol,
95
- srcTokenImage: srcToken?.image,
96
- srcAmount: tokenAmount === "0" ? "<0.0001" : tokenAmount,
97
- isDone: false,
98
- explorer: `${CCIP_EXPLORER}/tx/${txHash}`,
91
+ const timestamp = Date.now() / 1000;
92
+ const transaction: Transaction = {
93
+ hash: txReceipt.transactionHash,
94
+ timestamp,
95
+ sourceChainId: srcChain.chainId,
96
+ targetChainId: dstChain.chainId,
97
+ amountWei: MessageSentEventArgs?.tokenAmount.toString(),
98
+ tokenAddress: srcToken.address,
99
+ tokenOutAddress: dstToken?.address,
100
+ tokenOutAmount: dstTokenAmount,
101
+ estimatedDeliveryTimestamp:
102
+ MessageSentEventArgs?.valueForInstantCcipRecieve.toString() !== "0"
103
+ ? timestamp * 1000 + 30 * 1000
104
+ : timestamp * 1000 + 30 * 60 * 1000,
105
+ status: "IN_PROGRESS",
99
106
  };
100
107
 
101
- addTransactionToRenderedTransactions(transaction);
108
+ addTransactionToRenderedTransactions({
109
+ transaction,
110
+ supportedChains,
111
+ dstToken,
112
+ srcToken,
113
+ });
102
114
  renderTxStatusButtons();
103
115
 
104
116
  const xSwapRouterOnDestinationAddress = ADDRESSES[dstChainId]?.XSwapRouter;
@@ -134,20 +146,20 @@ export const renderTxStatus = async (
134
146
  getTxStatus({ transferId: messageId }).then((response) => {
135
147
  if (response.status === "DONE") {
136
148
  onSuccess();
149
+ } else {
150
+ setTimeout(
151
+ () =>
152
+ getTxStatus({ transferId: messageId }).then((response) => {
153
+ if (response.status === "DONE") {
154
+ onSuccess();
155
+ }
156
+ }),
157
+ 30 * 60 * 1000,
158
+ ); // additional check after 30 min
159
+
160
+ xSwapRouterOnDestination.once(msgReceivedEventFilter, () => onSuccess());
137
161
  }
138
162
  });
139
-
140
- setTimeout(
141
- () =>
142
- getTxStatus({ transferId: messageId }).then((response) => {
143
- if (response.status === "DONE") {
144
- onSuccess();
145
- }
146
- }),
147
- 30 * 60 * 1000,
148
- ); // additional check after 30 min
149
-
150
- xSwapRouterOnDestination.once(msgReceivedEventFilter, () => onSuccess());
151
163
  };
152
164
 
153
165
  const getTxReceipt = async (txChainId: string, txHash: string) => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  Chain,
3
- GetSwapTxPayload,
3
+ ModalIntegrationPayload,
4
4
  Transactions,
5
5
  Web3Environment,
6
6
  } from "@src/models";
@@ -12,27 +12,38 @@ export const openTransactionModal = async ({
12
12
  integratorId,
13
13
  dstChain,
14
14
  dstToken,
15
+ srcChain,
16
+ srcToken,
15
17
  customContractCalls = [],
16
18
  desc,
17
19
  returnTransactions,
18
20
  dstDisplayToken,
19
- }: GetSwapTxPayload): Promise<Transactions | undefined> => {
21
+ }: ModalIntegrationPayload): Promise<Transactions | undefined> => {
20
22
  const supportedChains: Chain[] = (await getChains()).filter(
21
23
  ({ web3Environment, swapSupported }) =>
22
24
  web3Environment === Web3Environment.MAINNET && swapSupported,
23
25
  );
24
26
 
25
- validateSwapTxData(supportedChains, dstChain, dstToken);
27
+ validateSwapTxData(
28
+ integratorId,
29
+ supportedChains,
30
+ dstChain,
31
+ dstToken,
32
+ srcChain,
33
+ srcToken,
34
+ );
26
35
 
27
36
  const route = await openTxConfigForm({
28
37
  integratorId,
29
38
  dstChainId: dstChain,
30
39
  dstTokenAddr: dstToken,
40
+ srcChainId: srcChain,
41
+ srcTokenAddr: srcToken,
31
42
  customContractCalls,
32
43
  desc,
33
- supportedChains,
34
44
  returnTransactions,
35
45
  dstDisplayTokenAddr: dstDisplayToken,
46
+ supportedChains,
36
47
  });
37
48
 
38
49
  if (returnTransactions) {
@@ -41,20 +52,53 @@ export const openTransactionModal = async ({
41
52
  };
42
53
 
43
54
  const validateSwapTxData = (
55
+ integratorId: string,
44
56
  supportedChains: Chain[],
45
57
  dstChain: string,
46
58
  dstToken: string,
59
+ srcChain?: string,
60
+ srcToken?: string,
47
61
  ) => {
62
+ if (!integratorId) {
63
+ throw new Error(
64
+ "Provide integratorId or contact the team to generate one.",
65
+ );
66
+ }
67
+
48
68
  const supportedDstChain = supportedChains.find(
49
69
  ({ chainId }) => chainId === dstChain,
50
70
  );
51
71
  if (!supportedDstChain) {
52
72
  throw new Error(`Provided chain '${dstChain}' is not supported`);
53
73
  }
54
-
55
- if (!isETHAddressValid(dstToken)) {
74
+ if (
75
+ !isETHAddressValid(dstToken) ||
76
+ supportedDstChain.tokens.findIndex(
77
+ ({ address }) => address === dstToken,
78
+ ) === -1
79
+ ) {
56
80
  throw new Error(
57
81
  `Provided token address ${dstToken} on chain ${dstChain} is invalid`,
58
82
  );
59
83
  }
84
+
85
+ if (srcChain) {
86
+ const supportedSrcChain = supportedChains.find(
87
+ ({ chainId }) => chainId === srcChain,
88
+ );
89
+ if (!supportedSrcChain) {
90
+ throw new Error(`Provided chain '${srcChain}' is not supported`);
91
+ }
92
+ if (
93
+ srcToken &&
94
+ (!isETHAddressValid(dstToken) ||
95
+ supportedSrcChain.tokens.findIndex(
96
+ ({ address }) => address === srcToken,
97
+ ) === -1)
98
+ ) {
99
+ throw new Error(
100
+ `Provided token address ${srcToken} on chain ${srcChain} is invalid`,
101
+ );
102
+ }
103
+ }
60
104
  };
@@ -175,3 +175,32 @@ export const findPlaceholderIndex = (
175
175
 
176
176
  return result;
177
177
  };
178
+
179
+ export const getEventsFromReceipt = async (
180
+ receipt: ethers.providers.TransactionReceipt,
181
+ abi: ethers.ContractInterface,
182
+ rpcUrl: string,
183
+ eventName: string,
184
+ ) => {
185
+ const contract = new ethers.Contract(
186
+ receipt.to,
187
+ abi,
188
+ ethers.getDefaultProvider(rpcUrl),
189
+ );
190
+
191
+ const eventSignature = contract.interface.getEvent(eventName).format();
192
+
193
+ return receipt.logs
194
+ .filter((log) => log.topics[0] === ethers.utils.id(eventSignature))
195
+ .map((log) => contract.interface.parseLog(log));
196
+ };
197
+
198
+ export const trimTxHash = (hash: string, beginAndEndCharacters: number = 5) => {
199
+ if (!hash) {
200
+ return "";
201
+ }
202
+ return `${hash?.substring(0, beginAndEndCharacters)}...${hash.substring(
203
+ hash.length - beginAndEndCharacters,
204
+ hash.length,
205
+ )}`;
206
+ };
@@ -1,7 +1,7 @@
1
1
  export * from "./contracts";
2
2
  export * from "./numbers";
3
- export * from "./strings";
4
3
  export * from "./parseWeb3Error";
4
+ export * from "./strings";
5
5
 
6
6
  import { format } from "date-fns";
7
7
 
@@ -27,9 +27,9 @@ export const deepMergeObjects = (
27
27
  obj2: Record<string, any>,
28
28
  ) => {
29
29
  for (const key in obj2) {
30
- if (obj2.hasOwnProperty(key)) {
30
+ if (Object.prototype.hasOwnProperty.call(obj2, key)) {
31
31
  if (
32
- obj1.hasOwnProperty(key) &&
32
+ Object.prototype.hasOwnProperty.call(obj1, key) &&
33
33
  typeof obj1[key] === "object" &&
34
34
  typeof obj2[key] === "object"
35
35
  ) {
@@ -30,6 +30,20 @@ export const weiToHumanReadable = ({
30
30
  return res;
31
31
  };
32
32
 
33
+ export const humanReadableToWei = ({
34
+ amount,
35
+ decimals,
36
+ }: {
37
+ amount: string;
38
+ decimals: number;
39
+ }): string => {
40
+ const decimalsFactor = Math.pow(10, decimals);
41
+ const parsedAmount = new BigNumberJS(amount || "0");
42
+ return safeBigNumberFrom(
43
+ parsedAmount.mul(decimalsFactor).toFixed(),
44
+ ).toString();
45
+ };
46
+
33
47
  export const generateRandomBigNumber = (length: number) => {
34
48
  return BigNumber.from(utils.randomBytes(length));
35
49
  };