@ensofinance/checkout-widget 0.0.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 (128) hide show
  1. package/dist/checkout-widget.es.js +52889 -0
  2. package/dist/checkout-widget.es.js.map +1 -0
  3. package/dist/checkout-widget.umd.js +203 -0
  4. package/dist/checkout-widget.umd.js.map +1 -0
  5. package/dist/index.d.ts +23 -0
  6. package/enso-api.yaml +1982 -0
  7. package/orval.config.ts +25 -0
  8. package/package.json +79 -0
  9. package/src/assets/BinanceBadge.svg +4 -0
  10. package/src/assets/CoinbaseIcon.svg +4 -0
  11. package/src/assets/USD Coin (USDC).svg +5 -0
  12. package/src/assets/avecIcon.svg +5 -0
  13. package/src/assets/base.webp +0 -0
  14. package/src/assets/depositIcon.svg +6 -0
  15. package/src/assets/eth.webp +0 -0
  16. package/src/assets/ethMainnetIcon.svg +10 -0
  17. package/src/assets/fail.svg +5 -0
  18. package/src/assets/kraken.png +0 -0
  19. package/src/assets/logo.svg +10 -0
  20. package/src/assets/mastercard.png +0 -0
  21. package/src/assets/metamask.png +0 -0
  22. package/src/assets/rabby.png +0 -0
  23. package/src/assets/success.svg +4 -0
  24. package/src/assets/usdc.webp +0 -0
  25. package/src/assets/usdt.webp +0 -0
  26. package/src/assets/visa.png +0 -0
  27. package/src/assets/visa.webp +0 -0
  28. package/src/components/BridgeFee.tsx +58 -0
  29. package/src/components/ChakraProvider.tsx +372 -0
  30. package/src/components/Checkout.tsx +127 -0
  31. package/src/components/CheckoutModal.tsx +22 -0
  32. package/src/components/CircleTimer.tsx +66 -0
  33. package/src/components/CurrencySwapDisplay.tsx +153 -0
  34. package/src/components/DepositProcessing.tsx +116 -0
  35. package/src/components/ExchangeConfirmSecurity.tsx +110 -0
  36. package/src/components/QuoteParameters.tsx +341 -0
  37. package/src/components/TransactionDetailRow.tsx +124 -0
  38. package/src/components/cards/AssetCard.tsx +167 -0
  39. package/src/components/cards/ExchangeCard.tsx +53 -0
  40. package/src/components/cards/OptionCard.tsx +59 -0
  41. package/src/components/cards/WalletCard.tsx +99 -0
  42. package/src/components/cards/index.ts +6 -0
  43. package/src/components/modal.tsx +83 -0
  44. package/src/components/steps/ExchangeFlow.tsx +1402 -0
  45. package/src/components/steps/InitialStep.tsx +169 -0
  46. package/src/components/steps/QuoteStep.tsx +121 -0
  47. package/src/components/steps/WalletAmountStep.tsx +258 -0
  48. package/src/components/steps/WalletConfirmStep.tsx +404 -0
  49. package/src/components/steps/WalletTokenStep.tsx +128 -0
  50. package/src/components/ui/index.tsx +394 -0
  51. package/src/components/ui/styled.tsx +85 -0
  52. package/src/components/ui/toaster.tsx +43 -0
  53. package/src/components/ui/tooltip.tsx +46 -0
  54. package/src/enso-api/api.ts +173 -0
  55. package/src/enso-api/custom-instance.ts +35 -0
  56. package/src/enso-api/index.ts +5119 -0
  57. package/src/enso-api/model/action.ts +17 -0
  58. package/src/enso-api/model/actionAction.ts +52 -0
  59. package/src/enso-api/model/actionInputs.ts +12 -0
  60. package/src/enso-api/model/actionToBundle.ts +19 -0
  61. package/src/enso-api/model/actionToBundleAction.ts +53 -0
  62. package/src/enso-api/model/actionToBundleArgs.ts +12 -0
  63. package/src/enso-api/model/bundleControllerBundleShortcutTransactionParams.ts +53 -0
  64. package/src/enso-api/model/bundleControllerBundleShortcutTransactionRoutingStrategy.ts +23 -0
  65. package/src/enso-api/model/bundleShortcutTransaction.ts +35 -0
  66. package/src/enso-api/model/bundleShortcutTransactionAmountsOut.ts +15 -0
  67. package/src/enso-api/model/bundleShortcutTransactionFeeAmount.ts +12 -0
  68. package/src/enso-api/model/connectedNetwork.ts +16 -0
  69. package/src/enso-api/model/hop.ts +24 -0
  70. package/src/enso-api/model/hopArgs.ts +12 -0
  71. package/src/enso-api/model/index.ts +70 -0
  72. package/src/enso-api/model/iporControllerIporShortcutTransactionParams.ts +21 -0
  73. package/src/enso-api/model/iporShortcutInput.ts +33 -0
  74. package/src/enso-api/model/iporShortcutTransaction.ts +22 -0
  75. package/src/enso-api/model/lZDestinationTokenData.ts +19 -0
  76. package/src/enso-api/model/lZPoolLookupResponse.ts +26 -0
  77. package/src/enso-api/model/layerZeroControllerGetPoolAddressParams.ts +29 -0
  78. package/src/enso-api/model/network.ts +15 -0
  79. package/src/enso-api/model/networksControllerNetworksParams.ts +21 -0
  80. package/src/enso-api/model/nonTokenizedControllerTokens200.ts +15 -0
  81. package/src/enso-api/model/nonTokenizedControllerTokens200AllOf.ts +16 -0
  82. package/src/enso-api/model/nonTokenizedControllerTokensParams.ts +41 -0
  83. package/src/enso-api/model/nonTokenizedModel.ts +27 -0
  84. package/src/enso-api/model/nontokenizedControllerRouteNontokenizedShorcutTransactionParams.ts +64 -0
  85. package/src/enso-api/model/nontokenizedControllerRouteNontokenizedShorcutTransactionRoutingStrategy.ts +22 -0
  86. package/src/enso-api/model/paginatedResult.ts +16 -0
  87. package/src/enso-api/model/paginationMeta.ts +27 -0
  88. package/src/enso-api/model/positionModel.ts +77 -0
  89. package/src/enso-api/model/price.ts +20 -0
  90. package/src/enso-api/model/pricesControllerGetPricesParams.ts +17 -0
  91. package/src/enso-api/model/project.ts +15 -0
  92. package/src/enso-api/model/protocol.ts +15 -0
  93. package/src/enso-api/model/protocolModel.ts +26 -0
  94. package/src/enso-api/model/protocolsControllerFindAllParams.ts +21 -0
  95. package/src/enso-api/model/routeShortcutTransaction.ts +33 -0
  96. package/src/enso-api/model/routeShortcutVariableInputs.ts +68 -0
  97. package/src/enso-api/model/routeShortcutVariableInputsRoutingStrategy.ts +27 -0
  98. package/src/enso-api/model/routeShortcutVariableInputsVariableEstimates.ts +14 -0
  99. package/src/enso-api/model/routerControllerRouteShortcutTransactionParams.ts +91 -0
  100. package/src/enso-api/model/routerControllerRouteShortcutTransactionRoutingStrategy.ts +23 -0
  101. package/src/enso-api/model/standard.ts +18 -0
  102. package/src/enso-api/model/standardAction.ts +20 -0
  103. package/src/enso-api/model/standardActionAction.ts +53 -0
  104. package/src/enso-api/model/tokenModel.ts +36 -0
  105. package/src/enso-api/model/tokensControllerTokens200.ts +15 -0
  106. package/src/enso-api/model/tokensControllerTokens200AllOf.ts +16 -0
  107. package/src/enso-api/model/tokensControllerTokensParams.ts +91 -0
  108. package/src/enso-api/model/tokensControllerTokensType.ts +19 -0
  109. package/src/enso-api/model/transaction.ts +17 -0
  110. package/src/enso-api/model/userOperation.ts +28 -0
  111. package/src/enso-api/model/walletApproveTransaction.ts +24 -0
  112. package/src/enso-api/model/walletApproveTransactionTx.ts +15 -0
  113. package/src/enso-api/model/walletBalance.ts +29 -0
  114. package/src/enso-api/model/walletControllerCreateApproveTransactionParams.ts +35 -0
  115. package/src/enso-api/model/walletControllerCreateApproveTransactionRoutingStrategy.ts +23 -0
  116. package/src/enso-api/model/walletControllerWalletBalancesParams.ts +25 -0
  117. package/src/index.ts +17 -0
  118. package/src/store.ts +68 -0
  119. package/src/types/assets.d.ts +29 -0
  120. package/src/types/index.ts +21 -0
  121. package/src/util/common.tsx +324 -0
  122. package/src/util/constants.tsx +213 -0
  123. package/src/util/enso-hooks.tsx +203 -0
  124. package/src/util/index.tsx +68 -0
  125. package/src/util/tx-tracker.tsx +301 -0
  126. package/src/util/wallet.tsx +258 -0
  127. package/tsconfig.json +13 -0
  128. package/vite.config.ts +51 -0
@@ -0,0 +1,203 @@
1
+ import {
2
+ useAccount,
3
+ useCapabilities,
4
+ useSendCalls,
5
+ useWalletClient,
6
+ } from "wagmi";
7
+ import { Address } from "viem";
8
+ import { useCallback, useMemo } from "react";
9
+ import { useEnsoToken, useEnsoPrice, useEnsoData } from "@/enso-api/api";
10
+ import { getWalletDisplayName, getWalletIcon } from "@/util/wallet";
11
+ import { formatUSD, normalizeValue } from "@/util";
12
+ import { useAppStore } from "@/store";
13
+ import { VITALIK_ADDRESS } from "./constants";
14
+
15
+ export const useAppDetails = () => {
16
+ const { address = VITALIK_ADDRESS } = useAccount();
17
+ const amountIn = useAppStore((state) => state.amountIn);
18
+ const tokenIn = useAppStore((state) => state.tokenIn);
19
+ const tokenOut = useAppStore((state) => state.tokenOut);
20
+ const slippage = useAppStore((state) => state.slippage);
21
+ const chainIdIn = useAppStore((state) => state.chainIdIn);
22
+ const chainIdOut = useAppStore((state) => state.chainIdOut);
23
+ const isCheckout = useAppStore((state) => state.isCheckout);
24
+
25
+ const {
26
+ data: [tokenInData],
27
+ } = useEnsoToken(tokenIn, chainIdIn);
28
+ const {
29
+ data: [tokenOutData],
30
+ } = useEnsoToken(tokenOut, chainIdOut);
31
+ const { data: tokenInPrice } = useEnsoPrice(chainIdIn, tokenIn);
32
+ const { data: tokenOutPrice } = useEnsoPrice(chainIdOut, tokenOut);
33
+
34
+ return {
35
+ chainIdIn,
36
+ chainIdOut,
37
+ tokenInData,
38
+ tokenOutData,
39
+ amountIn,
40
+ slippage,
41
+ address,
42
+ tokenInPrice,
43
+ tokenOutPrice,
44
+ tokenIn,
45
+ tokenOut,
46
+ isCheckout,
47
+ };
48
+ };
49
+
50
+ export const useSendTxns = ({
51
+ address,
52
+ chainId,
53
+ calls,
54
+ }: {
55
+ address: string;
56
+ chainId: number;
57
+ calls: any[];
58
+ }) => {
59
+ const { sendCalls } = useSendCalls();
60
+ const { data: caps } = useCapabilities();
61
+ // const atomicOkay = caps?.[chainId]?.atomic?.status === "ready";
62
+ const atomicOkay = false;
63
+ // const useFallback = !atomicOkay; // one-line policy; tweak to taste
64
+ const wallet = useWalletClient();
65
+
66
+ console.log(caps, atomicOkay);
67
+
68
+ const sendTxns = useCallback(
69
+ async (
70
+ onTxSend: (hash: string) => void,
71
+ onFail: (error: any) => void,
72
+ ) => {
73
+ if (!atomicOkay) {
74
+ // Send transactions sequentially when atomic is not supported
75
+ console.log(
76
+ "Atomic not supported, sending transactions sequentially",
77
+ );
78
+
79
+ try {
80
+ for (const call of calls) {
81
+ console.log("Sending individual transaction:", call);
82
+
83
+ const result = await wallet.data?.sendTransaction({
84
+ ...call,
85
+ account: address as Address,
86
+ chainId,
87
+ });
88
+
89
+ console.log("Sequential transaction result:", result);
90
+
91
+ // Check if transaction failed and stop execution
92
+ if (!result) {
93
+ throw new Error(
94
+ `Transaction failed for call: ${JSON.stringify(call)}`,
95
+ );
96
+ }
97
+
98
+ if (call === calls[calls.length - 1]) {
99
+ onTxSend(result);
100
+ }
101
+ }
102
+
103
+ console.log("All sequential transactions completed");
104
+ } catch (err) {
105
+ console.error("Error in sequential transaction:", err);
106
+ onFail(err);
107
+ throw err;
108
+ }
109
+ return;
110
+ }
111
+
112
+ // Use atomic transactions when supported
113
+ wallet.data
114
+ ?.sendCalls(
115
+ // @ts-ignore
116
+ {
117
+ calls,
118
+ account: address as Address,
119
+ forceAtomic: true, // request atomic only when possible
120
+ },
121
+ )
122
+ .then((result) => {
123
+ debugger;
124
+ console.log(result);
125
+ })
126
+ .catch((err) => {
127
+ debugger;
128
+ console.error(err);
129
+ onFail(err);
130
+ });
131
+ },
132
+ [sendCalls, calls, atomicOkay, chainId, wallet.data],
133
+ );
134
+
135
+ const ready = calls.length > 0 && wallet.data;
136
+
137
+ return {
138
+ ready,
139
+ sendTxns,
140
+ };
141
+ };
142
+
143
+ export const useRouteData = () => {
144
+ const {
145
+ tokenInData,
146
+ amountIn,
147
+ slippage,
148
+ address,
149
+ chainIdIn,
150
+ chainIdOut,
151
+ tokenInPrice,
152
+ tokenIn,
153
+ tokenOut,
154
+ isCheckout,
155
+ } = useAppDetails();
156
+
157
+ const {
158
+ data: routeData,
159
+ isLoading,
160
+ error,
161
+ isFetched,
162
+ } = useEnsoData({
163
+ routingStrategy: isCheckout ? "checkout" : "router",
164
+ fromAddress: address,
165
+ receiver: address,
166
+ spender: address,
167
+ amountIn,
168
+ tokenIn,
169
+ tokenOut,
170
+ slippage,
171
+ chainId: chainIdIn,
172
+ outChainId: chainIdOut,
173
+ });
174
+
175
+ const usdAmountIn = useMemo(
176
+ () =>
177
+ formatUSD(
178
+ normalizeValue(
179
+ (+amountIn * tokenInPrice).toFixed(),
180
+ tokenInData?.decimals,
181
+ ),
182
+ ),
183
+ [amountIn, tokenInPrice, tokenInData?.decimals],
184
+ );
185
+
186
+ return {
187
+ chainIdOut,
188
+ routeData,
189
+ routeFetched: isFetched,
190
+ routeLoading: isLoading,
191
+ usdAmountIn,
192
+ routerError: error,
193
+ };
194
+ };
195
+
196
+ export const useWalletIcon = () => {
197
+ const { connector } = useAccount();
198
+
199
+ return {
200
+ walletIcon: getWalletIcon(connector?.name),
201
+ walletDisplayName: getWalletDisplayName(connector?.name),
202
+ };
203
+ };
@@ -0,0 +1,68 @@
1
+ import { Address, formatUnits, parseUnits } from "viem";
2
+ import { STARGATE_CHAIN_NAMES } from "./constants";
3
+ import { useEffect, useRef } from "react";
4
+
5
+ export const denormalizeValue = (value: string, decimals = 0) =>
6
+ parseUnits(value, decimals).toString();
7
+
8
+ export const normalizeValue = (value: bigint | string = "0", decimals = 0) => {
9
+ try {
10
+ return formatUnits(BigInt(value), decimals);
11
+ } catch (e) {
12
+ console.error(e);
13
+ return "0";
14
+ }
15
+ };
16
+
17
+ export const compareCaseInsensitive = (a: string, b: string) => {
18
+ return !!(a && b && a?.toLowerCase() === b?.toLowerCase());
19
+ };
20
+
21
+ export const shortenAddress = (address: Address, short = false) =>
22
+ `${short ? "" : address.slice(0, 4)}...${address.slice(-4)}`;
23
+
24
+ const formatter = Intl.NumberFormat("en", {
25
+ maximumFractionDigits: 4,
26
+ });
27
+
28
+ const preciseFormatter = Intl.NumberFormat("en", {
29
+ maximumFractionDigits: 6,
30
+ });
31
+ const usdFormatter = Intl.NumberFormat("en", {
32
+ style: "currency",
33
+ currency: "USD",
34
+ });
35
+
36
+ export const formatNumber = (value: number | string, precise?: boolean) => {
37
+ const formatterToUse = precise ? preciseFormatter : formatter;
38
+
39
+ return isNaN(+value) ? "0.0" : formatterToUse.format(+value);
40
+ };
41
+
42
+ export const formatUSD = (value: number | string) => {
43
+ return usdFormatter.format(+value);
44
+ };
45
+
46
+ export const formatCompactUsd = (value: number | string) => {
47
+ const num = typeof value === "string" ? parseFloat(value) : value;
48
+
49
+ if (isNaN(num)) return "0";
50
+
51
+ const formatter = Intl.NumberFormat("en", {
52
+ notation: "compact",
53
+ maximumFractionDigits: 2,
54
+ });
55
+
56
+ return formatter.format(num);
57
+ };
58
+
59
+ export const getChainIcon = (chainId: number) =>
60
+ `https://icons-ckg.pages.dev/stargate-light/networks/${STARGATE_CHAIN_NAMES[chainId]}.svg`;
61
+
62
+ export const usePrevious = <T extends any>(value: T): T | undefined => {
63
+ const ref = useRef<T>();
64
+ useEffect(() => {
65
+ ref.current = value;
66
+ });
67
+ return ref.current;
68
+ };
@@ -0,0 +1,301 @@
1
+ import { ReactNode, useCallback, useEffect, useState } from "react";
2
+ import { useWaitForTransactionReceipt } from "wagmi";
3
+ import { create } from "zustand";
4
+ import { useQuery } from "@tanstack/react-query";
5
+ import { getChainEtherscanUrl } from "./common";
6
+ import { SupportedChainId } from "@/util/constants";
7
+
8
+ type TrackParams = {
9
+ hash: `0x${string}` | undefined;
10
+ chainId: SupportedChainId;
11
+ crosschain: boolean;
12
+ message: string;
13
+ onConfirmed: (
14
+ receipt: ReturnType<typeof useWaitForTransactionReceipt>["data"],
15
+ ) => void;
16
+ status?: string | ReactNode;
17
+ isActive?: boolean;
18
+ };
19
+
20
+ const useTrackingStore = create<{
21
+ txs: TrackParams[];
22
+ addTx: (tx: TrackParams) => void;
23
+ removeTx: (hash: `0x${string}`) => void;
24
+ updateTx: (hash: `0x${string}`, tx: Partial<TrackParams>) => void;
25
+ }>((set) => ({
26
+ txs: [],
27
+ addTx: (tx: TrackParams) => set((state) => ({ txs: [...state.txs, tx] })),
28
+ removeTx: (hash: `0x${string}`) =>
29
+ set((state) => ({ txs: state.txs.filter((tx) => tx.hash !== hash) })),
30
+ updateTx: (hash: `0x${string}`, tx: Partial<TrackParams>) =>
31
+ set((state) => ({
32
+ txs: state.txs.map((txn) =>
33
+ txn.hash === hash ? { ...txn, ...tx } : txn,
34
+ ),
35
+ })),
36
+ }));
37
+
38
+ export const useTxByHash = (hash: string) => {
39
+ const { txs } = useTrackingStore();
40
+
41
+ return txs.find((tx) => tx.hash === hash);
42
+ };
43
+
44
+ export const useTrackTx = () => {
45
+ const { addTx } = useTrackingStore();
46
+
47
+ const track = useCallback((args: TrackParams) => {
48
+ if (!args.hash) return;
49
+ addTx(args);
50
+ }, []);
51
+
52
+ return { track };
53
+ };
54
+
55
+ enum LayerZeroStatus {
56
+ Pending = "PENDING",
57
+ Success = "SUCCEEDED",
58
+ Failed = "FAILED",
59
+ Inflight = "INFLIGHT",
60
+ Confirming = "CONFIRMING",
61
+ Delivered = "DELIVERED",
62
+ }
63
+
64
+ const useLayerZeroUrl = (hash?: `0x${string}`, reset?: () => void) => {
65
+ // const [loadingToastId, setLoadingToastId] = useState<string>();
66
+ const updateTx = useTrackingStore((state) => state.updateTx);
67
+ const { data } = useQuery({
68
+ queryKey: ["layerZeroUrl", hash || "none", !!reset],
69
+ queryFn: async () => {
70
+ if (!hash) return null;
71
+ return fetch(
72
+ `https://scan.layerzero-api.com/v1/messages/tx/${hash}`,
73
+ )
74
+ .then((res) => res.json())
75
+ .then((res) => res.data[0]);
76
+ },
77
+ refetchInterval: 2000,
78
+ enabled: !!(reset && hash),
79
+ });
80
+
81
+ // useEffect(() => {
82
+ // if (data?.source?.status === LayerZeroStatus.Success) {
83
+ // updateTx(hash, {
84
+ // status: "(0/4) Waiting for source transaction completion",
85
+ // });
86
+ // }
87
+ // }, [data?.source?.status]);
88
+
89
+ useEffect(() => {
90
+ if (!hash) return;
91
+
92
+ // const action = {
93
+ // label: "View on Explorer",
94
+ // onClick: () =>
95
+ // window.open(`https://layerzeroscan.com/tx/${hash}`, "_blank"),
96
+ // };
97
+
98
+ // if (!loadingToastId) {
99
+
100
+ // toaster.create({
101
+ // id: hash,
102
+ // title: "Pending (0/4)",
103
+ // description: "Waiting for source transaction completion",
104
+ // type: "loading",
105
+ // action,
106
+ // });
107
+ // } else
108
+ if (
109
+ data?.source?.status &&
110
+ data.source.status !== LayerZeroStatus.Success
111
+ ) {
112
+ updateTx(hash, {
113
+ status: "(1/4) Waiting for funds to be sent on destination",
114
+ });
115
+ // toaster.update(loadingToastId, {
116
+ // title: "Pending (1/4)",
117
+ // description: "Waiting for funds to be sent on destination",
118
+ // });
119
+ } else if (data?.status?.name === LayerZeroStatus.Delivered) {
120
+ reset?.();
121
+ updateTx(hash, {
122
+ status: "(4/4) Bridging is complete",
123
+ isActive: false,
124
+ });
125
+ // toaster.update(loadingToastId, {
126
+ // title: "Success (4/4) ",
127
+ // description: "Bridging is complete",
128
+ // type: "success",
129
+ // action,
130
+ // });
131
+ // setLoadingToastId(undefined);
132
+ } else if (data?.status?.name === LayerZeroStatus.Confirming) {
133
+ updateTx(hash, {
134
+ status: "(3/4) Waiting for destination execution",
135
+ });
136
+ // toaster.update(loadingToastId, {
137
+ // title: "Pending (3/4)",
138
+ // description: "Waiting for destination execution",
139
+ // });
140
+ } else if (data?.status?.name === LayerZeroStatus.Inflight) {
141
+ updateTx(hash, {
142
+ status: "(2/4) Waiting for funds to be delivered on destination",
143
+ });
144
+ // toaster.update(loadingToastId, {
145
+ // title: "Pending (2/4)",
146
+ // description: "Waiting for funds to be delivered on destination",
147
+ // });
148
+ }
149
+ }, [data, hash]);
150
+ };
151
+
152
+ const useSingleChainTransactionTracking = (
153
+ hash: `0x${string}` | undefined,
154
+ chainId: SupportedChainId,
155
+ description: string,
156
+ waitForTransaction: ReturnType<typeof useWaitForTransactionReceipt>,
157
+ reset?: () => void,
158
+ ) => {
159
+ // const [loadingToastId, setLoadingToastId] = useState<string | undefined>();
160
+ const link = getChainEtherscanUrl({ hash, chainId });
161
+ const updateTx = useTrackingStore((state) => state.updateTx);
162
+
163
+ // toast error if tx failed to be mined and success if it is having confirmation
164
+ useEffect(() => {
165
+ if (!reset) return;
166
+
167
+ if (waitForTransaction.error) {
168
+ updateTx(hash, {
169
+ status: "Transaction Failed",
170
+ isActive: false,
171
+ });
172
+ // toaster.update(hash, {
173
+ // title: "Error",
174
+ // description: waitForTransaction.error.message,
175
+ // type: "error",
176
+ // action: link
177
+ // ? {
178
+ // label: "View on Explorer",
179
+ // onClick: () => window.open(link, "_blank"),
180
+ // }
181
+ // : undefined,
182
+ // });
183
+ } else if (waitForTransaction.data) {
184
+ // Close loading toast if it exists
185
+ // setLoadingToastId(undefined);
186
+ // reset tx hash to eliminate recurring notifications
187
+ reset?.();
188
+ updateTx(hash, {
189
+ status: "Transaction Confirmed",
190
+ isActive: false,
191
+ });
192
+
193
+ // toaster.update(loadingToastId, {
194
+ // title: "Success",
195
+ // description: description,
196
+ // type: "success",
197
+ // action: link
198
+ // ? {
199
+ // label: "View on Explorer",
200
+ // onClick: () => window.open(link, "_blank"),
201
+ // }
202
+ // : undefined,
203
+ // });
204
+ }
205
+ // else if (waitForTransaction.isLoading) {
206
+
207
+ // // if (!loadingToastId) {
208
+ // toaster.create({
209
+ // id: hash,
210
+ // title: "Transaction Pending",
211
+ // description: description,
212
+ // type: "loading",
213
+ // action: link
214
+ // ? {
215
+ // label: "View on Explorer",
216
+ // onClick: () => window.open(link, "_blank"),
217
+ // }
218
+ // : undefined,
219
+ // });
220
+ // setLoadingToastId(hash);
221
+ // }
222
+ // }
223
+ }, [
224
+ waitForTransaction.data,
225
+ waitForTransaction.error,
226
+ waitForTransaction.isLoading,
227
+ description,
228
+ link,
229
+ reset,
230
+ ]);
231
+ };
232
+
233
+ const SingleChainTracker = ({
234
+ hash,
235
+ chainId,
236
+ message = "Transaction confirmed",
237
+ onConfirmed,
238
+ }: Omit<TrackParams, "crosschain">) => {
239
+ const { removeTx } = useTrackingStore();
240
+ const receipt = useWaitForTransactionReceipt({
241
+ hash,
242
+ chainId,
243
+ });
244
+
245
+ useEffect(() => {
246
+ if (receipt.data) {
247
+ onConfirmed?.(receipt.data);
248
+ }
249
+ }, [receipt.data, onConfirmed]);
250
+
251
+ useSingleChainTransactionTracking(hash, chainId, message, receipt, () =>
252
+ removeTx(hash),
253
+ );
254
+
255
+ return null;
256
+ };
257
+
258
+ const CrosschainTracker = ({
259
+ hash,
260
+ chainId,
261
+ onConfirmed,
262
+ }: Omit<TrackParams, "crosschain" | "message">) => {
263
+ // const { removeTx } = useTrackingStore();
264
+ const receipt = useWaitForTransactionReceipt({
265
+ hash,
266
+ chainId,
267
+ });
268
+
269
+ // useEffect(() => {
270
+ // if (receipt.data) {
271
+ // onConfirmed?.(receipt.data);
272
+ // }
273
+ // }, [receipt.data, onConfirmed]);
274
+
275
+ useLayerZeroUrl(receipt.data ? hash : undefined, () =>
276
+ onConfirmed?.(receipt.data),
277
+ );
278
+
279
+ return null;
280
+ };
281
+
282
+ const Tracker = (props: TrackParams) => {
283
+ if (props.crosschain) {
284
+ return <CrosschainTracker {...props} />;
285
+ }
286
+ return <SingleChainTracker {...props} />;
287
+ };
288
+
289
+ export const TxTracker = () => {
290
+ const { txs } = useTrackingStore();
291
+
292
+ return (
293
+ <>
294
+ {txs
295
+ .filter((tx) => tx.isActive)
296
+ .map((tx) => (
297
+ <Tracker key={tx.hash} {...tx} />
298
+ ))}
299
+ </>
300
+ );
301
+ };