@xswap-link/sdk 0.2.0 → 0.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xswap-link/sdk",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "JavaScript SDK for XSwap platform",
5
5
  "homepage": "https://github.com/xswap-link/xswap-sdk",
6
6
  "repository": {
@@ -23,6 +23,7 @@
23
23
  "@tanstack/react-query": "^5.35.5",
24
24
  "@types/react": "18.2.0",
25
25
  "@types/react-dom": "18.2.0",
26
+ "async-retry": "^1.3.3",
26
27
  "bignumber.js": "4.0.4",
27
28
  "date-fns": "^3.6.0",
28
29
  "ethers": "^5.7.2",
@@ -33,6 +34,7 @@
33
34
  },
34
35
  "devDependencies": {
35
36
  "@changesets/cli": "^2.27.1",
37
+ "@types/async-retry": "^1.4.8",
36
38
  "@types/jest": "^29.5.12",
37
39
  "@types/node": "^20.11.17",
38
40
  "@typescript-eslint/eslint-plugin": "^7.1.0",
@@ -56,8 +58,8 @@
56
58
  },
57
59
  "scripts": {
58
60
  "build": "tsup src/index.ts --format cjs,esm --dts",
59
- "watch": "nodemon",
60
- "release": "pnpm run build && changeset publish",
61
+ "watch": "pnpm build && nodemon",
62
+ "release": "pnpm build && changeset publish",
61
63
  "lint": "tsc && eslint . --ext .ts",
62
64
  "test": "jest"
63
65
  }
@@ -0,0 +1,12 @@
1
+ import { ChainlinkCCIPIcon, XSwapBadgeIcon } from "@src/components/icons";
2
+
3
+ export const PoweredBy = () => {
4
+ return (
5
+ <div className="flex justify-center items-center gap-2 my-3">
6
+ <span className="text-x_grey">Powered by</span>
7
+ <XSwapBadgeIcon />
8
+ <span>✕</span>
9
+ <ChainlinkCCIPIcon />
10
+ </div>
11
+ );
12
+ };
@@ -1,15 +1,12 @@
1
1
  import "@src/global.css";
2
2
  import { MouseEvent, useMemo } from "react";
3
- import { createRoot, Root } from "react-dom/client";
4
3
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
5
4
  import { WagmiProvider } from "wagmi";
6
- import { getWagmiConfig } from "@src/config";
5
+ import { getWagmiConfig, xswapRoot } from "@src/config";
7
6
  import { Chain, ContractCall, Route } from "@src/models";
8
7
  import { CloseIcon } from "@src/components/icons/CloseIcon";
8
+ import { PoweredBy } from "@src/components/TxConfigForm/PoweredBy";
9
9
  import { Form } from "./Form";
10
- import { ChainlinkCCIPIcon, XSwapBadgeIcon } from "../icons";
11
- import { version } from "../../../package.json";
12
- import xswapConfig from "../../../xswap.config";
13
10
 
14
11
  export type TxConfigFormProps = {
15
12
  dstChainId: string;
@@ -67,13 +64,7 @@ const TxConfigForm = ({
67
64
  >
68
65
  <CloseIcon />
69
66
  </div>
70
-
71
- <div className="swappage__poweredby">
72
- <span>Powered by</span>
73
- <XSwapBadgeIcon />
74
- <span>✕</span>
75
- <ChainlinkCCIPIcon />
76
- </div>
67
+ <PoweredBy />
77
68
  </div>
78
69
  </div>
79
70
  </QueryClientProvider>
@@ -111,18 +102,3 @@ export const openTxConfigForm = async ({
111
102
  throw new Error(`XSwap component error, ${err}`);
112
103
  }
113
104
  };
114
-
115
- // skip on server-side integrations
116
- let xswapRoot: Root;
117
- if (typeof document !== "undefined") {
118
- const xswapStyleElement = document.createElement("link");
119
- xswapStyleElement.rel = "stylesheet";
120
- xswapStyleElement.type = "text/css";
121
- xswapStyleElement.href = `${xswapConfig.apiUrl}/sdk/css/${version}`;
122
- document.head.appendChild(xswapStyleElement);
123
-
124
- const xswapModalElement = document.createElement("div");
125
- xswapModalElement.setAttribute("id", "xswap-modal");
126
- document.body.appendChild(xswapModalElement);
127
- xswapRoot = createRoot(xswapModalElement);
128
- }
@@ -1,19 +1,20 @@
1
- import { FC, useState } from "react";
2
- import { createRoot } from "react-dom/client";
1
+ import { FC, useMemo, useState } from "react";
3
2
  import {
4
3
  ArrowLeftIcon,
5
4
  ArrowRightIcon,
6
5
  CheckIcon,
7
6
  CircularProgressIcon,
7
+ ArrowUpRightIcon,
8
+ XSwapLogo,
8
9
  } from "../icons";
9
- import { ArrowUpRightIcon, XSwapLogo } from "../icons";
10
10
  import { MonitoredTransaction } from "@src/models";
11
+ import { txStatusRoot } from "@src/config";
11
12
 
12
13
  interface Props {
13
14
  transaction: MonitoredTransaction;
14
15
  }
15
16
 
16
- export const TxHistoryButton: FC<Props> = ({ transaction }) => {
17
+ export const TxStatusButton: FC<Props> = ({ transaction }) => {
17
18
  const {
18
19
  fromChain,
19
20
  fromChainImage,
@@ -27,15 +28,28 @@ export const TxHistoryButton: FC<Props> = ({ transaction }) => {
27
28
  explorer,
28
29
  } = transaction;
29
30
  const [isWide, setIsWide] = useState(false);
31
+
32
+ const background = useMemo(
33
+ () =>
34
+ isDone
35
+ ? "bg-[rgba(2,2,2,1)] bg-gradient-to-r from-[rgba(76,175,80,0.2)] to-[rgba(46,125,50,0.2)]"
36
+ : "bg-[rgba(2,2,2,1)] bg-gradient-to-r from-[rgba(54,129,198,0.2)] to-[rgba(43,74,157,0.2)]",
37
+ [isDone],
38
+ );
39
+
40
+ const border = useMemo(
41
+ () =>
42
+ isDone
43
+ ? "border border-solid border-x_green_dark"
44
+ : "border border-solid border-x_blue_dark",
45
+ [isDone],
46
+ );
47
+
30
48
  return (
31
49
  <div className="flex gap-2" onClick={() => setIsWide((x: boolean) => !x)}>
32
50
  {isWide && (
33
51
  <div
34
- className={`flex items-center min-w-60 sm:w-[520px] text-white h-14 px-4 text-sm gap-3 rounded-xl bg-gradient-to-r ${
35
- isDone
36
- ? "from-[rgba(76,175,80,0.1)] to-[rgba(46,125,50,0.1)] border border-solid border-x_green_dark"
37
- : "from-[rgba(54,129,198,0.1)] to-[rgba(43,74,157,0.1)] border border-solid border-x_blue_dark"
38
- }`}
52
+ className={`flex items-center min-w-60 sm:w-[520px] text-white h-14 px-4 text-sm gap-3 rounded-xl ${background} ${border}`}
39
53
  >
40
54
  <div className="flex justify-between flex-col gap-2 sm:gap-5 sm:flex-row w-full">
41
55
  <div className="flex items-center gap-2">
@@ -77,12 +91,7 @@ export const TxHistoryButton: FC<Props> = ({ transaction }) => {
77
91
  </div>
78
92
  )}
79
93
  <div
80
- className={`text-white rounded-xl cursor-pointer bg-gradient-to-r
81
- ${
82
- isDone
83
- ? "from-[rgba(76,175,80,0.1)] to-[rgba(46,125,50,0.1)] border border-solid border-x_green_dark"
84
- : "from-[rgba(54,129,198,0.1)] to-[rgba(43,74,157,0.1)] border border-solid border-x_blue_dark"
85
- }`}
94
+ className={`text-white rounded-xl cursor-pointer ${background} ${border}`}
86
95
  >
87
96
  <div className="flex gap-2 items-center h-14 w-20 justify-center">
88
97
  <ArrowLeftIcon />
@@ -133,18 +142,9 @@ export const updateTransactionDoneInRenderedTransactions = (txHash: string) => {
133
142
  }
134
143
  };
135
144
 
136
- const historyElement = document.createElement("div");
137
- historyElement.setAttribute("id", "xswap-history");
138
- historyElement.setAttribute(
139
- "class",
140
- "absolute bottom-5 right-2 flex flex-col gap-3 pl-9 items-end w-full z-50",
141
- );
142
- document.body.appendChild(historyElement);
143
- const txHistoryButtonRoot = createRoot(historyElement);
144
-
145
- export const renderTxHistoryButtons = () => {
145
+ export const renderTxStatusButtons = () => {
146
146
  const buttons = renderedTransactions.map((item) => (
147
- <TxHistoryButton key={item.txHash} transaction={item} />
147
+ <TxStatusButton key={item.txHash} transaction={item} />
148
148
  ));
149
- txHistoryButtonRoot.render(buttons);
149
+ txStatusRoot.render(buttons);
150
150
  };
@@ -28,3 +28,7 @@
28
28
  border: 1px solid rgba(255, 255, 255, 0.1);
29
29
  }
30
30
  }
31
+
32
+ .xswap-tx-status {
33
+ @apply absolute bottom-5 right-2 flex flex-col gap-3 pl-9 items-end w-full z-50;
34
+ }
@@ -1,4 +1,4 @@
1
1
  export * from "./Alert";
2
2
  export * from "./TxConfigForm";
3
- export * from "./TxHistoryButton";
3
+ export * from "./TxStatusButton";
4
4
  export * from "./Skeleton";
@@ -1 +1,2 @@
1
1
  export * from "./wagmiConfig";
2
+ export * from "./init";
@@ -0,0 +1,31 @@
1
+ import { createRoot, Root } from "react-dom/client";
2
+ import xswapConfig from "../../xswap.config";
3
+ import { version } from "../../package.json";
4
+
5
+ export let xswapRoot: Root;
6
+ export let txStatusRoot: Root;
7
+
8
+ export const initDocument = () => {
9
+ if (typeof document === "undefined") {
10
+ throw new Error("Can't render XPay components from server side.");
11
+ }
12
+
13
+ fetch(`${xswapConfig.apiUrl}/sdk/css?data={"version": "${version}"}`).then(
14
+ async (css) => {
15
+ const style = document.createElement("style");
16
+ style.textContent = await css.text();
17
+ document.body.appendChild(style);
18
+ },
19
+ );
20
+
21
+ const xswapElement = document.createElement("div");
22
+ xswapElement.setAttribute("id", "xswap-modal");
23
+ document.body.appendChild(xswapElement);
24
+ xswapRoot = createRoot(xswapElement);
25
+
26
+ const txStatusElement = document.createElement("div");
27
+ txStatusElement.setAttribute("id", "xswap-tx-status");
28
+ txStatusElement.setAttribute("class", "xswap-tx-status");
29
+ document.body.appendChild(txStatusElement);
30
+ txStatusRoot = createRoot(txStatusElement);
31
+ };
@@ -10,3 +10,17 @@ export const ROUTE_TIMEOUT_MS = 5000;
10
10
  export const MINIMUM_DISPLAYED_TOKEN_AMOUNT = 0.0001;
11
11
  export const DEFAULT_SOURCE_CHAIN_ID = "1";
12
12
  export const CCIP_EXPLORER = "https://ccip.chain.link/";
13
+ export const TX_RECEIPT_STATUS_LIFETIME = 10000;
14
+
15
+ export const MSG_SENT_EVENT_SIG =
16
+ "MessageSent(bytes32,uint64,address,bytes,address,uint256,uint256,address,uint256)";
17
+
18
+ export const MSG_SENT_EVENT_ABI = [
19
+ "event MessageSent(bytes32 indexed messageId, uint64 indexed destinationChainSelector, address indexed sender, bytes data, address token, uint256 tokenAmount, uint256 valueForInstantCcipRecieve, address transferedToken, uint256 transferedTokenAmount)",
20
+ ];
21
+ export const MSG_RECEIVED_EVENT_SIG =
22
+ "MessageReceived(bytes32,uint64,address,bytes,address,uint256)";
23
+
24
+ export const MSG_RECEIVED_EVENT_ABI = [
25
+ "event MessageReceived(bytes32 indexed messageId, uint64 indexed sourceChainSelector, address indexed sender, bytes data, address token, uint256 tokenAmount)",
26
+ ];
package/src/index.ts CHANGED
@@ -1,6 +1,6 @@
1
- export * from "./components";
2
- export * from "./constants";
3
- export * from "./contracts";
4
- export * from "./models";
5
- export * from "./services";
6
- export * from "./utils";
1
+ import { initDocument } from "@src/config/init";
2
+
3
+ initDocument();
4
+
5
+ export * from "@src/models";
6
+ export { getSwapTx, monitorTransactionStatus } from "@src/services";
@@ -1,2 +1,3 @@
1
1
  export * from "./customCalls";
2
+ export * from "./monitoring";
2
3
  export * from "./transactions";
@@ -0,0 +1,148 @@
1
+ import { Chain, MonitoredTransaction, Web3Environment } from "@src/models";
2
+ import { getChains } from "@src/services";
3
+ import { ethers } from "ethers";
4
+ import { weiToHumanReadable } from "@src/utils";
5
+ import {
6
+ CCIP_EXPLORER,
7
+ MSG_RECEIVED_EVENT_ABI,
8
+ MSG_RECEIVED_EVENT_SIG,
9
+ MSG_SENT_EVENT_ABI,
10
+ MSG_SENT_EVENT_SIG,
11
+ TX_RECEIPT_STATUS_LIFETIME,
12
+ } from "@src/constants";
13
+ import {
14
+ addTransactionToRenderedTransactions,
15
+ removeTransactionFromRenderedTransactions,
16
+ renderTxStatusButtons,
17
+ updateTransactionDoneInRenderedTransactions,
18
+ } from "@src/components";
19
+ import { ADDRESSES } from "@src/contracts";
20
+ import retry from "async-retry";
21
+
22
+ export const monitorTransactionStatus = async (
23
+ txChainId: string,
24
+ txHash: string,
25
+ ): Promise<void> => {
26
+ const txReceipt = await getTxReceipt(txChainId, txHash);
27
+
28
+ const supportedChains: Chain[] = (await getChains()).filter(
29
+ ({ web3Environment, swapSupported }) =>
30
+ web3Environment === Web3Environment.MAINNET && swapSupported,
31
+ );
32
+
33
+ const messageSentEvent = txReceipt.logs?.find((log: { topics: string[] }) => {
34
+ return log.topics[0] === ethers.utils.id(MSG_SENT_EVENT_SIG);
35
+ });
36
+
37
+ if (!messageSentEvent) {
38
+ throw new Error(
39
+ `No transaction event found for chain ${txChainId} tx ${txHash}`,
40
+ );
41
+ }
42
+
43
+ const messageId = messageSentEvent?.topics[1] as string;
44
+ const iface = new ethers.utils.Interface(MSG_SENT_EVENT_ABI);
45
+ const decodedMessageSentEvent = iface.parseLog(messageSentEvent);
46
+
47
+ if (!decodedMessageSentEvent) {
48
+ throw new Error(
49
+ `No transaction event arguments found for chain ${txChainId} tx ${txHash}`,
50
+ );
51
+ }
52
+ const srcChain = supportedChains.find(
53
+ (chain) => chain.chainId === txChainId.toString(),
54
+ );
55
+
56
+ const srcToken = srcChain?.tokens.find(
57
+ (token) => token.address === decodedMessageSentEvent.args?.token.toString(),
58
+ );
59
+
60
+ const dstChain = supportedChains.find(
61
+ (chain) =>
62
+ chain.ccipChainId ===
63
+ decodedMessageSentEvent.args?.destinationChainSelector?.toString(),
64
+ );
65
+
66
+ const dstChainId = dstChain?.chainId;
67
+
68
+ if (!dstChainId) {
69
+ throw new Error(`Unknown destination chain!`);
70
+ }
71
+
72
+ const transaction: MonitoredTransaction = {
73
+ txHash: txHash,
74
+ fromChain: srcChain?.displayName,
75
+ fromChainImage: srcChain?.image,
76
+ toChain: dstChain.displayName,
77
+ toChainImage: dstChain.image,
78
+ fromToken: srcToken?.symbol,
79
+ fromTokenImage: srcToken?.image,
80
+ fromAmount: weiToHumanReadable({
81
+ amount: decodedMessageSentEvent.args?.tokenAmount.toString(),
82
+ decimals: srcToken?.decimals || 18,
83
+ precisionFractionalPlaces: 4,
84
+ }),
85
+ isDone: false,
86
+ explorer: `${CCIP_EXPLORER}/tx/${txHash}`,
87
+ };
88
+
89
+ addTransactionToRenderedTransactions(transaction);
90
+ renderTxStatusButtons();
91
+
92
+ // start listening
93
+ // TODO if someone will provide tx which already is done then we will never get the event. Will need to add status endpoint on backend for transactions to check if they are done or not.
94
+
95
+ const xSwapRouterOnDestinationAddress = ADDRESSES[dstChainId]?.XSwapRouter;
96
+ if (!xSwapRouterOnDestinationAddress) {
97
+ throw new Error(`Unknown destination XSwapRouter!`);
98
+ }
99
+
100
+ const xSwapRouterOnDestination = new ethers.Contract(
101
+ xSwapRouterOnDestinationAddress,
102
+ MSG_RECEIVED_EVENT_ABI,
103
+ ethers.getDefaultProvider(
104
+ supportedChains.find((chain) => chain.chainId === dstChainId)
105
+ ?.publicRpcUrls[0],
106
+ ),
107
+ );
108
+
109
+ const msgReceivedEventFilter = {
110
+ address: xSwapRouterOnDestinationAddress,
111
+ topics: [ethers.utils.id(MSG_RECEIVED_EVENT_SIG), messageId],
112
+ };
113
+
114
+ const onSuccess = async () => {
115
+ updateTransactionDoneInRenderedTransactions(txHash);
116
+ renderTxStatusButtons();
117
+ await new Promise((resolve) =>
118
+ setTimeout(() => resolve(true), TX_RECEIPT_STATUS_LIFETIME),
119
+ );
120
+ removeTransactionFromRenderedTransactions(txHash);
121
+ renderTxStatusButtons();
122
+ };
123
+ xSwapRouterOnDestination.once(msgReceivedEventFilter, () => onSuccess());
124
+ };
125
+
126
+ const getTxReceipt = async (txChainId: string, txHash: string) => {
127
+ try {
128
+ const chain = (await getChains()).find(
129
+ (chain) => chain.chainId === txChainId,
130
+ );
131
+
132
+ const provider = new ethers.providers.JsonRpcProvider(
133
+ chain?.publicRpcUrls[0],
134
+ );
135
+
136
+ return await retry(async () => {
137
+ const txReceipt = await provider.getTransactionReceipt(txHash);
138
+ if (!txReceipt) {
139
+ throw new Error(`Couldn't fetch tx receipt`);
140
+ }
141
+ return txReceipt;
142
+ });
143
+ } catch (e) {
144
+ throw new Error(
145
+ `Couldn't fetch tx ${txHash} receipt on chain ${txChainId}`,
146
+ );
147
+ }
148
+ };
@@ -3,20 +3,9 @@ import {
3
3
  GetSwapTxPayload,
4
4
  Transactions,
5
5
  Web3Environment,
6
- MonitoredTransaction,
7
6
  } from "@src/models";
8
7
  import { getChains } from "@src/services";
9
- import { ethers } from "ethers";
10
- import { ADDRESSES } from "@src/contracts";
11
- import {
12
- openTxConfigForm,
13
- addTransactionToRenderedTransactions,
14
- removeTransactionFromRenderedTransactions,
15
- renderTxHistoryButtons,
16
- updateTransactionDoneInRenderedTransactions,
17
- } from "@src/components";
18
- import { weiToHumanReadable } from "@src/utils";
19
- import { CCIP_EXPLORER } from "@src/constants";
8
+ import { openTxConfigForm } from "@src/components";
20
9
 
21
10
  export const getSwapTx = async ({
22
11
  dstChain,
@@ -58,138 +47,3 @@ const validateSwapTxData = (
58
47
  throw new Error(`Provided token '${dstToken}' is not supported`);
59
48
  }
60
49
  };
61
-
62
- export const monitorTransactionStatus = async (
63
- srcChainId: number,
64
- txHash: string,
65
- ) => {
66
- const txReceipt = await getTxReceipt(srcChainId, txHash);
67
-
68
- if (!txReceipt) {
69
- throw new Error(
70
- `No transaction found for chain ${srcChainId} tx ${txHash}`,
71
- );
72
- }
73
-
74
- const supportedChains: Chain[] = (await getChains()).filter(
75
- ({ web3Environment, swapSupported }) =>
76
- web3Environment === Web3Environment.MAINNET && swapSupported,
77
- );
78
-
79
- const messageSentEventSignature =
80
- "MessageSent(bytes32,uint64,address,bytes,address,uint256,uint256,address,uint256)";
81
-
82
- const messageSentEventAbi = [
83
- "event MessageSent(bytes32 indexed messageId, uint64 indexed destinationChainSelector, address indexed sender, bytes data, address token, uint256 tokenAmount, uint256 valueForInstantCcipRecieve, address transferedToken, uint256 transferedTokenAmount)",
84
- ];
85
- const messageReceivedEventSignature =
86
- "MessageReceived(bytes32,uint64,address,bytes,address,uint256)";
87
-
88
- const messageReceivedEventAbi = [
89
- "event MessageReceived(bytes32 indexed messageId, uint64 indexed sourceChainSelector, address indexed sender, bytes data, address token, uint256 tokenAmount)",
90
- ];
91
-
92
- const messageSentEvent = txReceipt.logs?.find((log) => {
93
- return log.topics[0] === ethers.utils.id(messageSentEventSignature);
94
- });
95
-
96
- if (!messageSentEvent) {
97
- throw new Error(
98
- `No transaction event found for chain ${srcChainId} tx ${txHash}`,
99
- );
100
- }
101
-
102
- const messageId = messageSentEvent?.topics[1] as string;
103
- const iface = new ethers.utils.Interface(messageSentEventAbi);
104
- const decodedMessageSentEvent = iface.parseLog(messageSentEvent);
105
-
106
- if (!decodedMessageSentEvent) {
107
- throw new Error(
108
- `No transaction event arguments found for chain ${srcChainId} tx ${txHash}`,
109
- );
110
- }
111
- const srcChain = supportedChains.find(
112
- (chain) => chain.chainId === srcChainId.toString(),
113
- );
114
-
115
- const srcToken = srcChain?.tokens.find(
116
- (token) => token.address === decodedMessageSentEvent.args?.token.toString(),
117
- );
118
-
119
- const targetChain = supportedChains.find(
120
- (chain) =>
121
- chain.ccipChainId ===
122
- decodedMessageSentEvent.args?.destinationChainSelector?.toString(),
123
- );
124
-
125
- const toChainId = targetChain?.chainId;
126
-
127
- if (!toChainId) {
128
- throw new Error(`Unknown destination chain!`);
129
- }
130
-
131
- const transaction: MonitoredTransaction = {
132
- txHash: txHash,
133
- fromChain: srcChain?.displayName,
134
- fromChainImage: srcChain?.image,
135
- toChain: targetChain.displayName,
136
- toChainImage: targetChain.image,
137
- fromToken: srcToken?.symbol,
138
- fromTokenImage: srcToken?.image,
139
- fromAmount: weiToHumanReadable({
140
- amount: decodedMessageSentEvent.args?.tokenAmount.toString(),
141
- decimals: srcToken?.decimals || 18,
142
- precisionFractionalPlaces: 4,
143
- }),
144
- isDone: false,
145
- explorer: `${CCIP_EXPLORER}/tx/${txHash}`,
146
- };
147
-
148
- addTransactionToRenderedTransactions(transaction);
149
- renderTxHistoryButtons();
150
-
151
- // start listening
152
- // TODO if someone will provide tx which already is done then we will never get the event. Will need to add status endpoint on backend for transactions to check if they are done or not.
153
-
154
- const xSwapRouterOnDestinationAddress = ADDRESSES[toChainId]?.XSwapRouter;
155
- if (!xSwapRouterOnDestinationAddress) {
156
- throw new Error(`Unknown destination XSwapRouter!`);
157
- }
158
-
159
- const xSwapRouterOnDestination = new ethers.Contract(
160
- xSwapRouterOnDestinationAddress,
161
- messageReceivedEventAbi,
162
- ethers.getDefaultProvider(
163
- supportedChains.find((chain) => chain.chainId === toChainId)
164
- ?.publicRpcUrls[0],
165
- ),
166
- );
167
-
168
- const eventFilter = {
169
- address: xSwapRouterOnDestinationAddress,
170
- topics: [ethers.utils.id(messageReceivedEventSignature), messageId],
171
- };
172
-
173
- const onSuccess = async () => {
174
- updateTransactionDoneInRenderedTransactions(txHash);
175
- renderTxHistoryButtons();
176
- await new Promise((resolve) => setTimeout(() => resolve(true), 5000));
177
- removeTransactionFromRenderedTransactions(txHash);
178
- renderTxHistoryButtons();
179
- };
180
- xSwapRouterOnDestination.once(eventFilter, () => onSuccess());
181
- };
182
-
183
- const getTxReceipt = async (txChainId: number, txHash: string) => {
184
- const chains = await getChains();
185
- const chain = chains.find((chain) => chain.chainId === txChainId.toString());
186
- const provider = new ethers.providers.JsonRpcProvider(
187
- chain?.publicRpcUrls[0],
188
- );
189
- try {
190
- return await provider.getTransactionReceipt(txHash);
191
- } catch (error) {
192
- console.error("Error fetching transaction receipt:", error);
193
- return null;
194
- }
195
- };
@@ -8,6 +8,7 @@ module.exports = {
8
8
  x_alert_light: "rgb(255,226,183)",
9
9
  x_blue: "#3396FF",
10
10
  x_green: "#66bb6a",
11
+ x_grey: "#ffffff80",
11
12
  x_error_background: "rgba(255,202,40,0.1)",
12
13
  x_error_border: "rgba(255,111,0,1)",
13
14
  x_blue_light: "rgba(54,129,198,1)",