@0xsquid/react-hooks 1.0.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 (108) hide show
  1. package/.babelrc +7 -0
  2. package/.eslintignore +1 -0
  3. package/.eslintrc.json +44 -0
  4. package/dist/index.js +6 -0
  5. package/jest.config.ts +28 -0
  6. package/package.json +124 -0
  7. package/scripts/copyAssets.js +27 -0
  8. package/scripts/removeBuildTestFolder.js +28 -0
  9. package/scripts/replacePaths.js +37 -0
  10. package/src/assets/images/icons/wallets/binance.svg +4 -0
  11. package/src/assets/images/icons/wallets/bitget.svg +43 -0
  12. package/src/assets/images/icons/wallets/bitkeep.svg +9 -0
  13. package/src/assets/images/icons/wallets/blockchaindotcom.svg +11 -0
  14. package/src/assets/images/icons/wallets/brave.svg +18 -0
  15. package/src/assets/images/icons/wallets/c98.svg +3 -0
  16. package/src/assets/images/icons/wallets/coinbase.svg +5 -0
  17. package/src/assets/images/icons/wallets/cosmostation.svg +9 -0
  18. package/src/assets/images/icons/wallets/defiConnect.svg +25 -0
  19. package/src/assets/images/icons/wallets/exodus.svg +33 -0
  20. package/src/assets/images/icons/wallets/fetchai.svg +1 -0
  21. package/src/assets/images/icons/wallets/index.ts +43 -0
  22. package/src/assets/images/icons/wallets/keplr.svg +9 -0
  23. package/src/assets/images/icons/wallets/leap.svg +35 -0
  24. package/src/assets/images/icons/wallets/metamask.svg +48 -0
  25. package/src/assets/images/icons/wallets/okx.svg +1 -0
  26. package/src/assets/images/icons/wallets/rabby.svg +1 -0
  27. package/src/assets/images/icons/wallets/trustwallet.svg +11 -0
  28. package/src/assets/images/icons/wallets/walletConnect.svg +11 -0
  29. package/src/assets/images/icons/wallets/wallet_icon.svg +1 -0
  30. package/src/assets/images/icons/wallets/xdefi.svg +9 -0
  31. package/src/assets/images/icons/wallets/zerion.svg +11 -0
  32. package/src/connectors/ExodusConnector.ts +6 -0
  33. package/src/connectors/LedgerLiveConnector.ts +226 -0
  34. package/src/contracts/typechain/ERC20.d.ts +441 -0
  35. package/src/contracts/typechain/factories/ERC20__factory.d.ts +56 -0
  36. package/src/contracts/typechain/factories/ERC20__factory.ts +340 -0
  37. package/src/core/constants.ts +549 -0
  38. package/src/core/externalLinks.ts +26 -0
  39. package/src/core/index.ts +1 -0
  40. package/src/core/multicall3.ts +22 -0
  41. package/src/core/numbers.ts +44 -0
  42. package/src/core/providers/CosmosProvider.tsx +55 -0
  43. package/src/core/queries/queries-keys.ts +156 -0
  44. package/src/core/queries/react-query-config.ts +13 -0
  45. package/src/core/types/components.ts +16 -0
  46. package/src/core/types/config.ts +52 -0
  47. package/src/core/types/dex.ts +31 -0
  48. package/src/core/types/error.ts +52 -0
  49. package/src/core/types/event.ts +16 -0
  50. package/src/core/types/route.ts +21 -0
  51. package/src/core/types/swap.ts +8 -0
  52. package/src/core/types/tokens.ts +30 -0
  53. package/src/core/types/transaction.ts +84 -0
  54. package/src/core/types/types.ts +37 -0
  55. package/src/core/types/wallet.ts +83 -0
  56. package/src/hooks/chains/useSquidChains.ts +66 -0
  57. package/src/hooks/cosmos/useCosmos.ts +279 -0
  58. package/src/hooks/cosmos/useCosmosForChain.ts +33 -0
  59. package/src/hooks/index.ts +32 -0
  60. package/src/hooks/navigation/useKeyboardNavigation.ts +88 -0
  61. package/src/hooks/store/useSquidStore.ts +80 -0
  62. package/src/hooks/swap/useSwap.ts +359 -0
  63. package/src/hooks/tokens/useAllTokensWithBalance.ts +157 -0
  64. package/src/hooks/tokens/useBalance.ts +180 -0
  65. package/src/hooks/tokens/useMultiChainBalance.ts +59 -0
  66. package/src/hooks/tokens/usePrices.ts +52 -0
  67. package/src/hooks/tokens/useSingleTokenPrice.ts +45 -0
  68. package/src/hooks/tokens/useSquidTokens.ts +48 -0
  69. package/src/hooks/tokens/useTokensWithBalance.ts +169 -0
  70. package/src/hooks/transaction/useEstimate.ts +397 -0
  71. package/src/hooks/transaction/useEstimatePriceImpact.ts +39 -0
  72. package/src/hooks/transaction/useExecuteTransaction.ts +440 -0
  73. package/src/hooks/transaction/useExpress.ts +46 -0
  74. package/src/hooks/transaction/useGetRoute.ts +145 -0
  75. package/src/hooks/transaction/useSingleTransaction.ts +155 -0
  76. package/src/hooks/transaction/useTransaction.ts +734 -0
  77. package/src/hooks/user/useUserParams.ts +63 -0
  78. package/src/hooks/wallet/useAddToken.ts +53 -0
  79. package/src/hooks/wallet/useAutoConnect.ts +56 -0
  80. package/src/hooks/wallet/useGnosisContext.ts +84 -0
  81. package/src/hooks/wallet/useIntegratorContext.ts +44 -0
  82. package/src/hooks/wallet/useMultiChainWallet.ts +146 -0
  83. package/src/hooks/wallet/useWallet.ts +86 -0
  84. package/src/hooks/webapp-router/useSquidRouter.ts +42 -0
  85. package/src/index.ts +5 -0
  86. package/src/provider/index.tsx +105 -0
  87. package/src/react-app-env.d.ts +2 -0
  88. package/src/services/external/analyticsService.ts +46 -0
  89. package/src/services/external/coingeckoService.ts +35 -0
  90. package/src/services/external/rpcService.ts +196 -0
  91. package/src/services/external/secretService.ts +178 -0
  92. package/src/services/index.ts +1 -0
  93. package/src/services/internal/apiService.ts +6 -0
  94. package/src/services/internal/assetsService.ts +84 -0
  95. package/src/services/internal/configService.ts +261 -0
  96. package/src/services/internal/errorService.ts +124 -0
  97. package/src/services/internal/eventService.ts +93 -0
  98. package/src/services/internal/priceService.ts +10 -0
  99. package/src/services/internal/transactionService.ts +255 -0
  100. package/src/services/internal/transactionStatusService.ts +293 -0
  101. package/src/services/internal/walletService.ts +158 -0
  102. package/src/tests/assetsService.test.ts +176 -0
  103. package/src/tests/configService.test.ts +486 -0
  104. package/src/tests/fetchSquidData.ts +43 -0
  105. package/src/tests/jest-svg-transform.ts +19 -0
  106. package/src/tests/sample.json +0 -0
  107. package/src/tests/walletService.test.ts +178 -0
  108. package/tsconfig.json +30 -0
@@ -0,0 +1,59 @@
1
+ import { useCosmosBalance, useEvmBalance } from "@/hooks/tokens/useBalance";
2
+ import type {
3
+ ChainData,
4
+ CosmosChain,
5
+ EvmChain,
6
+ Token,
7
+ } from "@0xsquid/sdk/dist/types";
8
+ import { ChainType } from "@0xsquid/sdk/dist/types";
9
+ import { useMemo } from "react";
10
+
11
+ /**
12
+ * Exposes a hook to get balance depending on the chain type (EVM or Cosmos)
13
+ * @param {ChainData} chain
14
+ * @param {Token} token
15
+ * @param {string} userAddress
16
+ * @param {boolean} enabled
17
+ * @returns balance as string
18
+ */
19
+ export const useMultiChainBalance = ({
20
+ chain,
21
+ token,
22
+ userAddress,
23
+ enabled = true,
24
+ }: {
25
+ chain?: ChainData;
26
+ token?: Token;
27
+ userAddress?: string;
28
+ enabled?: boolean;
29
+ }) => {
30
+ /**
31
+ * Get balance for EVM chain types
32
+ */
33
+ const { balance: evmBalance } = useEvmBalance({
34
+ chain: chain as EvmChain,
35
+ token,
36
+ userAddress: userAddress ?? "",
37
+ enabled: chain?.chainType === ChainType.EVM && enabled,
38
+ });
39
+
40
+ /**
41
+ * Get balance for Cosmos chain types
42
+ */
43
+ const { balance: cosmosBalance } = useCosmosBalance({
44
+ chainData: chain as CosmosChain,
45
+ token,
46
+ userAddress,
47
+ });
48
+
49
+ /**
50
+ * Get either EVM or cosmos Balance
51
+ */
52
+ const balance = useMemo(
53
+ () =>
54
+ chain?.chainType === ChainType.EVM ? evmBalance.data : cosmosBalance,
55
+ [evmBalance.data, chain, cosmosBalance]
56
+ );
57
+
58
+ return { balance };
59
+ };
@@ -0,0 +1,52 @@
1
+ import { keys } from "@/core/queries/queries-keys";
2
+ import {
3
+ useSquidStore,
4
+ useSwapRoutePersistStore,
5
+ } from "@/hooks/store/useSquidStore";
6
+ import { fetchPriceForToken } from "@/services/external/coingeckoService";
7
+ import { useQuery } from "@tanstack/react-query";
8
+
9
+ export const usePrices = () => {
10
+ const { squid, config } = useSquidStore();
11
+ const { swapRoute } = useSwapRoutePersistStore();
12
+
13
+ /**
14
+ * Get token prices from Squid API
15
+ */
16
+ const tokenPrices = useQuery(
17
+ keys({ apiUrl: config.apiUrl }).tokensPrice(swapRoute),
18
+ async () => {
19
+ const result = await Promise.all([
20
+ // From
21
+ fetchPriceForToken({
22
+ apiUrl: config.apiUrl,
23
+ chainId: swapRoute?.fromChainId?.toString(),
24
+ tokenAddress: swapRoute?.fromTokenAddress,
25
+ integratorId: config.integratorId,
26
+ }),
27
+ // To
28
+ fetchPriceForToken({
29
+ apiUrl: config.apiUrl,
30
+ chainId: swapRoute?.toChainId?.toString(),
31
+ tokenAddress: swapRoute?.toTokenAddress,
32
+ integratorId: config.integratorId,
33
+ }),
34
+ ]);
35
+
36
+ return {
37
+ sourceTokenUsdPrice: result[0] as number,
38
+ destinationTokenUsdPrice: result[1] as number,
39
+ };
40
+ },
41
+ {
42
+ enabled:
43
+ swapRoute &&
44
+ !!squid &&
45
+ !!swapRoute?.fromChainId &&
46
+ !!swapRoute?.toChainId &&
47
+ !!swapRoute?.toTokenAddress &&
48
+ !!swapRoute?.fromTokenAddress,
49
+ }
50
+ );
51
+ return { tokenPrices };
52
+ };
@@ -0,0 +1,45 @@
1
+ import { keys } from "@/core/queries/queries-keys";
2
+ import { useSquidStore } from "@/hooks/store/useSquidStore";
3
+ import { fetchPriceForToken } from "@/services/external/coingeckoService";
4
+ import type { Token } from "@0xsquid/sdk/dist/types";
5
+ import { useQuery } from "@tanstack/react-query";
6
+ import { useAccount } from "wagmi";
7
+
8
+ /**
9
+ * If a component need to display price of a single token
10
+ * @param tokenData
11
+ * @returns
12
+ */
13
+ export const useSingleTokenPrice = (
14
+ tokenData: Pick<Token, "address" | "chainId"> | undefined
15
+ ) => {
16
+ const { config } = useSquidStore();
17
+ const { address } = useAccount();
18
+
19
+ /**
20
+ * Get token price from Squid api
21
+ * Using coingecko under the hood
22
+ */
23
+ const tokenPrice = useQuery(
24
+ keys({ address, apiUrl: config.apiUrl }).singleTokenPrice(
25
+ tokenData?.address,
26
+ tokenData?.chainId
27
+ ),
28
+ async () => {
29
+ const price = await fetchPriceForToken({
30
+ apiUrl: config.apiUrl,
31
+ chainId: tokenData?.chainId.toString(),
32
+ tokenAddress: tokenData?.address,
33
+ integratorId: config.integratorId,
34
+ });
35
+
36
+ return price;
37
+ }
38
+ );
39
+
40
+ const getUSDValue = (balance: string) => {
41
+ return parseFloat(tokenPrice.data?.toString() ?? "0") * parseFloat(balance);
42
+ };
43
+
44
+ return { tokenPrice, getUSDValue };
45
+ };
@@ -0,0 +1,48 @@
1
+ import { useSquidStore } from "@/hooks/store/useSquidStore";
2
+ import { useMemo } from "react";
3
+
4
+ export const useSquidTokens = () => {
5
+ const { squid, config } = useSquidStore();
6
+
7
+ const fuseSearchOptions = {
8
+ isCaseSensitive: false,
9
+ threshold: 0.1,
10
+ findAllMatches: false,
11
+ includeMatches: true,
12
+
13
+ keys: [
14
+ {
15
+ name: "symbol",
16
+ weight: 1, // highest relevance
17
+ },
18
+ {
19
+ name: "name",
20
+ weight: 0.8, // slightly less relevance than symbol
21
+ },
22
+ ],
23
+ };
24
+
25
+ const tokens = useMemo(() => {
26
+ const unavailableChainIds = config.comingSoonChainIds?.map(String) ?? [];
27
+
28
+ // Remove tokens with same chainId and address
29
+ // and those from unavailable chains
30
+ const filteredTokens = squid?.tokens.filter((token, index, self) => {
31
+ const isTokenUnique =
32
+ index ===
33
+ self.findIndex(
34
+ (t) => t.chainId === token.chainId && t.address === token.address
35
+ );
36
+
37
+ const isUnavailableChainId = unavailableChainIds.includes(
38
+ String(token.chainId)
39
+ );
40
+
41
+ return isTokenUnique && !isUnavailableChainId;
42
+ });
43
+
44
+ return filteredTokens ?? [];
45
+ }, [squid?.tokens]);
46
+
47
+ return { tokens, fuseSearchOptions };
48
+ };
@@ -0,0 +1,169 @@
1
+ import { useCosmosContext } from "@/core/providers/CosmosProvider";
2
+ import { keys } from "@/core/queries/queries-keys";
3
+ import { TokenWithBalance } from "@/core/types/tokens";
4
+ import { useCosmosForChain } from "@/hooks/cosmos/useCosmosForChain";
5
+ import { useSquidStore } from "@/hooks/store/useSquidStore";
6
+ import { useSquidTokens } from "@/hooks/tokens/useSquidTokens";
7
+ import { fetchPriceForToken } from "@/services/external/coingeckoService";
8
+ import {
9
+ getAllEvmTokensBalance,
10
+ getWorkingCosmosRpcUrl,
11
+ } from "@/services/external/rpcService";
12
+ import {
13
+ SECRET_CHAIN_ID,
14
+ fetchAllSecretBalances,
15
+ } from "@/services/external/secretService";
16
+ import type { ChainData, Token } from "@0xsquid/squid-types";
17
+ import { ChainType } from "@0xsquid/squid-types";
18
+ import { StargateClient } from "@cosmjs/stargate";
19
+ import { useQuery } from "@tanstack/react-query";
20
+ import { formatUnits } from "ethers/lib/utils";
21
+
22
+ // TODO: Move this to a service
23
+ const getAllCosmosBalances = async ({
24
+ rpc,
25
+ address,
26
+ tokens,
27
+ }: {
28
+ rpc: string;
29
+ tokens: Token[];
30
+ address: string;
31
+ }) => {
32
+ const client = await StargateClient.connect(rpc);
33
+ const balanceAsCoin = await client.getAllBalances(address);
34
+
35
+ // Need to map tokens and put balance, based on denom
36
+ const tokensWithBalance = tokens.map((t) => {
37
+ const balanceCoin = balanceAsCoin?.find((c) => c.denom === t.address);
38
+ return {
39
+ ...t,
40
+ balance: balanceCoin
41
+ ? formatUnits(balanceCoin?.amount, t?.decimals)
42
+ : "0",
43
+ } as TokenWithBalance;
44
+ });
45
+
46
+ return tokensWithBalance;
47
+ };
48
+
49
+ export const useAllTokensWithBalanceForChain = (
50
+ chainData?: ChainData,
51
+ address: string = ""
52
+ ) => {
53
+ const { config } = useSquidStore();
54
+
55
+ const { tokens: squidTokens } = useSquidTokens();
56
+ const { keplrTypeWallet, isConnected: isCosmosConnected } =
57
+ useCosmosContext();
58
+ const { cosmosAddress } = useCosmosForChain(chainData);
59
+
60
+ const tokens = (squidTokens.filter((t) => t.chainId === chainData?.chainId) ??
61
+ []) as Token[];
62
+
63
+ const evmBalances = useQuery<TokenWithBalance[]>(
64
+ keys({
65
+ apiUrl: config.apiUrl,
66
+ address,
67
+ }).tokensBalanceForChain(chainData?.chainType, chainData?.chainId),
68
+ async () => {
69
+ if (chainData && tokens) {
70
+ const tokensBalance = await getAllEvmTokensBalance(tokens, address);
71
+
72
+ // Get Token usd price only for tokens which have balance > 0
73
+ const tokenUSDPrices = await Promise.all(
74
+ tokensBalance?.map((t, _) => {
75
+ if (+t.balance !== 0) {
76
+ return fetchPriceForToken({
77
+ apiUrl: config.apiUrl,
78
+ chainId: t?.chainId.toString(),
79
+ tokenAddress: t?.address,
80
+ integratorId: config.integratorId,
81
+ });
82
+ }
83
+ return 0;
84
+ }) ?? []
85
+ );
86
+
87
+ return (
88
+ tokensBalance?.map((token, index) => {
89
+ return {
90
+ ...token,
91
+ balance: token.balance,
92
+ priceUSD: tokenUSDPrices[index].toString(),
93
+ };
94
+ }) ?? []
95
+ );
96
+ }
97
+ return tokens?.map((s) => ({ ...s, balance: "" })) ?? [];
98
+ },
99
+ {
100
+ enabled: chainData?.chainType === ChainType.EVM && !!tokens,
101
+ }
102
+ );
103
+
104
+ const cosmosBalances = useQuery<TokenWithBalance[]>(
105
+ keys({
106
+ apiUrl: config.apiUrl,
107
+ address,
108
+ }).tokensBalanceForChain(chainData?.chainType, chainData?.chainId),
109
+ async () => {
110
+ if (chainData) {
111
+ if (chainData.chainId === SECRET_CHAIN_ID && isCosmosConnected) {
112
+ const squidSecretTokens = squidTokens.filter(
113
+ (t) => t.chainId === SECRET_CHAIN_ID
114
+ ) as Token[];
115
+
116
+ const secretTokens = await fetchAllSecretBalances(
117
+ chainData!,
118
+ cosmosAddress!,
119
+ squidSecretTokens,
120
+ keplrTypeWallet
121
+ );
122
+
123
+ return secretTokens;
124
+ }
125
+
126
+ const rpc = await getWorkingCosmosRpcUrl(chainData);
127
+ const balances = await getAllCosmosBalances({
128
+ address,
129
+ rpc,
130
+ tokens,
131
+ });
132
+ // Get Token usd price only for tokens which have balance > 0
133
+ const tokenUSDPrices = await Promise.all(
134
+ balances?.map((t, _) => {
135
+ if (+t.balance !== 0) {
136
+ return fetchPriceForToken({
137
+ apiUrl: config.apiUrl,
138
+ chainId: t?.chainId.toString(),
139
+ tokenAddress: t?.address,
140
+ });
141
+ }
142
+ return 0;
143
+ }) ?? []
144
+ );
145
+
146
+ return (
147
+ balances?.map((token, index) => {
148
+ return {
149
+ ...token,
150
+ balance: token.balance,
151
+ priceUSD: tokenUSDPrices[index].toString(),
152
+ };
153
+ }) ?? []
154
+ );
155
+ }
156
+ return [];
157
+ },
158
+ {
159
+ retry: false,
160
+ enabled:
161
+ chainData?.chainType === ChainType.COSMOS &&
162
+ !!tokens &&
163
+ !!address &&
164
+ address.length > 0,
165
+ }
166
+ );
167
+
168
+ return { evmBalances, cosmosBalances, tokens };
169
+ };