@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.
- package/.babelrc +7 -0
- package/.eslintignore +1 -0
- package/.eslintrc.json +44 -0
- package/dist/index.js +6 -0
- package/jest.config.ts +28 -0
- package/package.json +124 -0
- package/scripts/copyAssets.js +27 -0
- package/scripts/removeBuildTestFolder.js +28 -0
- package/scripts/replacePaths.js +37 -0
- package/src/assets/images/icons/wallets/binance.svg +4 -0
- package/src/assets/images/icons/wallets/bitget.svg +43 -0
- package/src/assets/images/icons/wallets/bitkeep.svg +9 -0
- package/src/assets/images/icons/wallets/blockchaindotcom.svg +11 -0
- package/src/assets/images/icons/wallets/brave.svg +18 -0
- package/src/assets/images/icons/wallets/c98.svg +3 -0
- package/src/assets/images/icons/wallets/coinbase.svg +5 -0
- package/src/assets/images/icons/wallets/cosmostation.svg +9 -0
- package/src/assets/images/icons/wallets/defiConnect.svg +25 -0
- package/src/assets/images/icons/wallets/exodus.svg +33 -0
- package/src/assets/images/icons/wallets/fetchai.svg +1 -0
- package/src/assets/images/icons/wallets/index.ts +43 -0
- package/src/assets/images/icons/wallets/keplr.svg +9 -0
- package/src/assets/images/icons/wallets/leap.svg +35 -0
- package/src/assets/images/icons/wallets/metamask.svg +48 -0
- package/src/assets/images/icons/wallets/okx.svg +1 -0
- package/src/assets/images/icons/wallets/rabby.svg +1 -0
- package/src/assets/images/icons/wallets/trustwallet.svg +11 -0
- package/src/assets/images/icons/wallets/walletConnect.svg +11 -0
- package/src/assets/images/icons/wallets/wallet_icon.svg +1 -0
- package/src/assets/images/icons/wallets/xdefi.svg +9 -0
- package/src/assets/images/icons/wallets/zerion.svg +11 -0
- package/src/connectors/ExodusConnector.ts +6 -0
- package/src/connectors/LedgerLiveConnector.ts +226 -0
- package/src/contracts/typechain/ERC20.d.ts +441 -0
- package/src/contracts/typechain/factories/ERC20__factory.d.ts +56 -0
- package/src/contracts/typechain/factories/ERC20__factory.ts +340 -0
- package/src/core/constants.ts +549 -0
- package/src/core/externalLinks.ts +26 -0
- package/src/core/index.ts +1 -0
- package/src/core/multicall3.ts +22 -0
- package/src/core/numbers.ts +44 -0
- package/src/core/providers/CosmosProvider.tsx +55 -0
- package/src/core/queries/queries-keys.ts +156 -0
- package/src/core/queries/react-query-config.ts +13 -0
- package/src/core/types/components.ts +16 -0
- package/src/core/types/config.ts +52 -0
- package/src/core/types/dex.ts +31 -0
- package/src/core/types/error.ts +52 -0
- package/src/core/types/event.ts +16 -0
- package/src/core/types/route.ts +21 -0
- package/src/core/types/swap.ts +8 -0
- package/src/core/types/tokens.ts +30 -0
- package/src/core/types/transaction.ts +84 -0
- package/src/core/types/types.ts +37 -0
- package/src/core/types/wallet.ts +83 -0
- package/src/hooks/chains/useSquidChains.ts +66 -0
- package/src/hooks/cosmos/useCosmos.ts +279 -0
- package/src/hooks/cosmos/useCosmosForChain.ts +33 -0
- package/src/hooks/index.ts +32 -0
- package/src/hooks/navigation/useKeyboardNavigation.ts +88 -0
- package/src/hooks/store/useSquidStore.ts +80 -0
- package/src/hooks/swap/useSwap.ts +359 -0
- package/src/hooks/tokens/useAllTokensWithBalance.ts +157 -0
- package/src/hooks/tokens/useBalance.ts +180 -0
- package/src/hooks/tokens/useMultiChainBalance.ts +59 -0
- package/src/hooks/tokens/usePrices.ts +52 -0
- package/src/hooks/tokens/useSingleTokenPrice.ts +45 -0
- package/src/hooks/tokens/useSquidTokens.ts +48 -0
- package/src/hooks/tokens/useTokensWithBalance.ts +169 -0
- package/src/hooks/transaction/useEstimate.ts +397 -0
- package/src/hooks/transaction/useEstimatePriceImpact.ts +39 -0
- package/src/hooks/transaction/useExecuteTransaction.ts +440 -0
- package/src/hooks/transaction/useExpress.ts +46 -0
- package/src/hooks/transaction/useGetRoute.ts +145 -0
- package/src/hooks/transaction/useSingleTransaction.ts +155 -0
- package/src/hooks/transaction/useTransaction.ts +734 -0
- package/src/hooks/user/useUserParams.ts +63 -0
- package/src/hooks/wallet/useAddToken.ts +53 -0
- package/src/hooks/wallet/useAutoConnect.ts +56 -0
- package/src/hooks/wallet/useGnosisContext.ts +84 -0
- package/src/hooks/wallet/useIntegratorContext.ts +44 -0
- package/src/hooks/wallet/useMultiChainWallet.ts +146 -0
- package/src/hooks/wallet/useWallet.ts +86 -0
- package/src/hooks/webapp-router/useSquidRouter.ts +42 -0
- package/src/index.ts +5 -0
- package/src/provider/index.tsx +105 -0
- package/src/react-app-env.d.ts +2 -0
- package/src/services/external/analyticsService.ts +46 -0
- package/src/services/external/coingeckoService.ts +35 -0
- package/src/services/external/rpcService.ts +196 -0
- package/src/services/external/secretService.ts +178 -0
- package/src/services/index.ts +1 -0
- package/src/services/internal/apiService.ts +6 -0
- package/src/services/internal/assetsService.ts +84 -0
- package/src/services/internal/configService.ts +261 -0
- package/src/services/internal/errorService.ts +124 -0
- package/src/services/internal/eventService.ts +93 -0
- package/src/services/internal/priceService.ts +10 -0
- package/src/services/internal/transactionService.ts +255 -0
- package/src/services/internal/transactionStatusService.ts +293 -0
- package/src/services/internal/walletService.ts +158 -0
- package/src/tests/assetsService.test.ts +176 -0
- package/src/tests/configService.test.ts +486 -0
- package/src/tests/fetchSquidData.ts +43 -0
- package/src/tests/jest-svg-transform.ts +19 -0
- package/src/tests/sample.json +0 -0
- package/src/tests/walletService.test.ts +178 -0
- package/tsconfig.json +30 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { wallets } from "@/core/constants";
|
|
2
|
+
import { Wallet } from "@/core/types/wallet";
|
|
3
|
+
import { useSwapRoutePersistStore } from "@/hooks/store/useSquidStore";
|
|
4
|
+
import { useSwap } from "@/hooks/swap/useSwap";
|
|
5
|
+
import {
|
|
6
|
+
accessProperty,
|
|
7
|
+
getCosmosChainInfosObject,
|
|
8
|
+
getDescendantProp,
|
|
9
|
+
} from "@/services/internal/walletService";
|
|
10
|
+
import type { ChainData } from "@0xsquid/sdk/dist/types";
|
|
11
|
+
import { ChainType } from "@0xsquid/sdk/dist/types";
|
|
12
|
+
import { CosmosSnap, installSnap } from "@cosmsnap/snapper";
|
|
13
|
+
import type { Keplr, OfflineDirectSigner } from "@keplr-wallet/types";
|
|
14
|
+
import { useMutation } from "@tanstack/react-query";
|
|
15
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
16
|
+
|
|
17
|
+
declare const window: any;
|
|
18
|
+
|
|
19
|
+
export const useCosmos = () => {
|
|
20
|
+
const [cosmosAddress, setCosmosAddress] = useState<string | undefined>();
|
|
21
|
+
const [cosmosSigner, setCosmosSigner] = useState<
|
|
22
|
+
OfflineDirectSigner | undefined
|
|
23
|
+
>(undefined);
|
|
24
|
+
const [cosmosConnectedWallet, setCosmosConnectedWallet] = useState<
|
|
25
|
+
Wallet | undefined
|
|
26
|
+
>();
|
|
27
|
+
const [cosmosChainId, setCosmosChainId] = useState<string | undefined>();
|
|
28
|
+
const [isConnected, setIsConnected] = useState(false);
|
|
29
|
+
const [isInstalled, setIsInstalled] = useState(false);
|
|
30
|
+
const { swapRoute } = useSwapRoutePersistStore();
|
|
31
|
+
const { fromChain } = useSwap();
|
|
32
|
+
|
|
33
|
+
const keplrTypeWallet: Keplr = useMemo(() => {
|
|
34
|
+
if (window && cosmosConnectedWallet?.windowFlag) {
|
|
35
|
+
return accessProperty(window, cosmosConnectedWallet.windowFlag) as Keplr;
|
|
36
|
+
}
|
|
37
|
+
// By default, return Cosmos wallet to be Keplr wallet
|
|
38
|
+
// Because like Metamask, some wallets will override the window.keplr Provider
|
|
39
|
+
// Meaning that this could be the current user wallet, so we can use it as a fallback
|
|
40
|
+
return window.keplr as Keplr;
|
|
41
|
+
}, [cosmosConnectedWallet]);
|
|
42
|
+
|
|
43
|
+
// As soon as from chain changes, need to fetch the new signer
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (fromChain?.chainType === ChainType.COSMOS && keplrTypeWallet) {
|
|
46
|
+
setCosmosSigner(
|
|
47
|
+
keplrTypeWallet.getOfflineSigner(fromChain?.chainId.toString())
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}, [fromChain?.chainId, fromChain?.chainType, keplrTypeWallet]);
|
|
51
|
+
|
|
52
|
+
const getCosmosAddressForChain = useCallback(
|
|
53
|
+
async (chainId?: string) => {
|
|
54
|
+
if (!chainId || !keplrTypeWallet) return undefined;
|
|
55
|
+
const key = await keplrTypeWallet?.getKey(chainId);
|
|
56
|
+
return key.bech32Address;
|
|
57
|
+
},
|
|
58
|
+
[keplrTypeWallet]
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const getCosmosWalletInfos = useMutation(
|
|
62
|
+
async ({
|
|
63
|
+
chainId,
|
|
64
|
+
cosmosWalletObject,
|
|
65
|
+
}: {
|
|
66
|
+
chainId: string;
|
|
67
|
+
cosmosWalletObject?: Keplr;
|
|
68
|
+
}): Promise<string | undefined> => {
|
|
69
|
+
const walletObject = cosmosWalletObject ?? keplrTypeWallet;
|
|
70
|
+
if (walletObject) {
|
|
71
|
+
const address = await walletObject?.getKey(chainId);
|
|
72
|
+
if (address?.bech32Address) {
|
|
73
|
+
return address.bech32Address;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const getAddress = useCallback(
|
|
81
|
+
async ({
|
|
82
|
+
wallet,
|
|
83
|
+
cosmosWalletObject,
|
|
84
|
+
chainId,
|
|
85
|
+
}: {
|
|
86
|
+
wallet: Wallet;
|
|
87
|
+
cosmosWalletObject: any;
|
|
88
|
+
chainId: string;
|
|
89
|
+
}): Promise<string> => {
|
|
90
|
+
if (wallet.connectorId === "snapper") {
|
|
91
|
+
const { address: addressInfo } =
|
|
92
|
+
await cosmosWalletObject.getBech32Address(chainId);
|
|
93
|
+
return addressInfo.address;
|
|
94
|
+
}
|
|
95
|
+
const address = await getCosmosWalletInfos.mutateAsync({
|
|
96
|
+
chainId,
|
|
97
|
+
cosmosWalletObject,
|
|
98
|
+
});
|
|
99
|
+
return address ?? "";
|
|
100
|
+
},
|
|
101
|
+
[getCosmosWalletInfos]
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
const handleKeplrAccountChanged = useCallback(async () => {
|
|
105
|
+
if (cosmosChainId) {
|
|
106
|
+
const address = await getCosmosWalletInfos.mutateAsync({
|
|
107
|
+
chainId: cosmosChainId,
|
|
108
|
+
});
|
|
109
|
+
if (address) {
|
|
110
|
+
setIsConnected(true);
|
|
111
|
+
setCosmosAddress(address);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}, [cosmosChainId, getCosmosWalletInfos]);
|
|
115
|
+
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
window.addEventListener("keplr_keystorechange", () =>
|
|
118
|
+
handleKeplrAccountChanged()
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
return () => {
|
|
122
|
+
window.removeEventListener("keplr_keystorechange", () =>
|
|
123
|
+
handleKeplrAccountChanged()
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
}, [handleKeplrAccountChanged]);
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* If needed, prepare the wallet object and return it
|
|
130
|
+
* Example: install Metamask snaps (Snapper)
|
|
131
|
+
* @param wallet
|
|
132
|
+
* @param cosmosWalletObject
|
|
133
|
+
* @returns
|
|
134
|
+
*/
|
|
135
|
+
const prepareCosmosWallet = async (
|
|
136
|
+
wallet: Wallet,
|
|
137
|
+
cosmosWalletObject?: any
|
|
138
|
+
): Promise<any> => {
|
|
139
|
+
let cwo = cosmosWalletObject;
|
|
140
|
+
switch (wallet.connectorId) {
|
|
141
|
+
case "snapper":
|
|
142
|
+
cwo = new CosmosSnap();
|
|
143
|
+
// await installSnap();
|
|
144
|
+
window[wallet?.windowFlag ?? ""] = cwo;
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
return cwo;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const connectCosmos = useMutation(
|
|
151
|
+
async ({
|
|
152
|
+
chain,
|
|
153
|
+
wallet,
|
|
154
|
+
direction,
|
|
155
|
+
}: {
|
|
156
|
+
chain: ChainData;
|
|
157
|
+
wallet?: Wallet;
|
|
158
|
+
direction?: "from" | "to";
|
|
159
|
+
}) => {
|
|
160
|
+
const chainInfos = getCosmosChainInfosObject(chain);
|
|
161
|
+
|
|
162
|
+
const selectedWallet =
|
|
163
|
+
wallet ??
|
|
164
|
+
cosmosConnectedWallet ??
|
|
165
|
+
wallets?.find((w) => w.connectorId === "keplr");
|
|
166
|
+
|
|
167
|
+
let cosmosWalletObject = selectedWallet
|
|
168
|
+
? getDescendantProp(window, selectedWallet.windowFlag)
|
|
169
|
+
: undefined;
|
|
170
|
+
|
|
171
|
+
// Some wallets need to be installed | initialized
|
|
172
|
+
if (selectedWallet) {
|
|
173
|
+
cosmosWalletObject = await prepareCosmosWallet(
|
|
174
|
+
selectedWallet,
|
|
175
|
+
cosmosWalletObject
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (cosmosWalletObject) {
|
|
180
|
+
setCosmosChainId(chainInfos.chainId.toString());
|
|
181
|
+
try {
|
|
182
|
+
if (selectedWallet?.connectorId === "snapper") {
|
|
183
|
+
await installSnap();
|
|
184
|
+
} else {
|
|
185
|
+
await cosmosWalletObject.enable(chainInfos.chainId.toString());
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const address = await getAddress({
|
|
189
|
+
chainId: chain.chainId.toString(),
|
|
190
|
+
cosmosWalletObject,
|
|
191
|
+
wallet: selectedWallet as any,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
if (address) {
|
|
195
|
+
setCosmosConnectedWallet(selectedWallet);
|
|
196
|
+
setIsConnected(true);
|
|
197
|
+
setCosmosAddress(address);
|
|
198
|
+
|
|
199
|
+
useSwapRoutePersistStore.setState({
|
|
200
|
+
swapRoute: {
|
|
201
|
+
...useSwapRoutePersistStore.getState().swapRoute,
|
|
202
|
+
destinationAddress:
|
|
203
|
+
direction === "to"
|
|
204
|
+
? address
|
|
205
|
+
: useSwapRoutePersistStore.getState().swapRoute
|
|
206
|
+
?.destinationAddress,
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
} catch (error) {
|
|
211
|
+
const e = error as {
|
|
212
|
+
module?: string;
|
|
213
|
+
code?: number;
|
|
214
|
+
message?: string;
|
|
215
|
+
};
|
|
216
|
+
if (
|
|
217
|
+
e.message !== "Request rejected" &&
|
|
218
|
+
e.message !== "User rejected the request."
|
|
219
|
+
) {
|
|
220
|
+
// Maybe the chain is not supported ?
|
|
221
|
+
if (cosmosWalletObject.experimentalSuggestChain) {
|
|
222
|
+
try {
|
|
223
|
+
await cosmosWalletObject.experimentalSuggestChain(chainInfos);
|
|
224
|
+
// Now try to connect
|
|
225
|
+
connectCosmos.mutate({ chain });
|
|
226
|
+
} catch (experimentalSuggestChainError) {
|
|
227
|
+
console.log(
|
|
228
|
+
"Failed to suggest chain",
|
|
229
|
+
experimentalSuggestChainError
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
} else {
|
|
236
|
+
setIsInstalled(false);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
const clearData = () => {
|
|
242
|
+
setIsConnected(false);
|
|
243
|
+
setCosmosChainId(undefined);
|
|
244
|
+
setCosmosAddress(undefined);
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const onCosmosChainChange = (newChainId: string) => {
|
|
248
|
+
if (newChainId !== cosmosChainId) {
|
|
249
|
+
clearData();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
useSwapRoutePersistStore.setState({
|
|
253
|
+
swapRoute: { ...swapRoute },
|
|
254
|
+
destinationAddressHasBeenUpdated: {
|
|
255
|
+
updated: false,
|
|
256
|
+
filledFromWallet: false,
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
connectCosmos,
|
|
263
|
+
cosmosChainId,
|
|
264
|
+
setCosmosChainId,
|
|
265
|
+
isConnected,
|
|
266
|
+
setIsConnected,
|
|
267
|
+
isInstalled,
|
|
268
|
+
setIsInstalled,
|
|
269
|
+
clearData,
|
|
270
|
+
onCosmosChainChange,
|
|
271
|
+
getAddress,
|
|
272
|
+
cosmosConnectedWallet,
|
|
273
|
+
keplrTypeWallet,
|
|
274
|
+
cosmosSigner,
|
|
275
|
+
getCosmosAddressForChain,
|
|
276
|
+
getCosmosWalletInfos,
|
|
277
|
+
cosmosAddress,
|
|
278
|
+
};
|
|
279
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useCosmosContext } from "@/core/providers/CosmosProvider";
|
|
2
|
+
import type { ChainData } from "@0xsquid/squid-types";
|
|
3
|
+
import { ChainType } from "@0xsquid/squid-types";
|
|
4
|
+
import { useQuery } from "@tanstack/react-query";
|
|
5
|
+
|
|
6
|
+
export const useCosmosForChain = (chainData?: ChainData) => {
|
|
7
|
+
const {
|
|
8
|
+
cosmosChainId: chainId,
|
|
9
|
+
cosmosAddress: userAddr,
|
|
10
|
+
isConnected,
|
|
11
|
+
} = useCosmosContext();
|
|
12
|
+
const { keplrTypeWallet } = useCosmosContext();
|
|
13
|
+
|
|
14
|
+
const cosmosAddress = useQuery(
|
|
15
|
+
["cosmos-address", chainData?.chainId, userAddr, isConnected],
|
|
16
|
+
async () => {
|
|
17
|
+
if (!isConnected) return undefined;
|
|
18
|
+
const key = await keplrTypeWallet?.getKey(String(chainData?.chainId));
|
|
19
|
+
return key?.bech32Address;
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
enabled:
|
|
23
|
+
!!keplrTypeWallet &&
|
|
24
|
+
!!chainId &&
|
|
25
|
+
!!userAddr &&
|
|
26
|
+
chainData?.chainType === ChainType.COSMOS,
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
cosmosAddress: cosmosAddress.data,
|
|
32
|
+
};
|
|
33
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export { useSquidChains } from "./chains/useSquidChains";
|
|
2
|
+
export { useCosmos } from "./cosmos/useCosmos";
|
|
3
|
+
export { useCosmosForChain } from "./cosmos/useCosmosForChain";
|
|
4
|
+
export { useKeyboardNavigation } from "./navigation/useKeyboardNavigation";
|
|
5
|
+
export { useSquidStore } from "./store/useSquidStore";
|
|
6
|
+
|
|
7
|
+
export { useSwap } from "./swap/useSwap";
|
|
8
|
+
export { useAllTokensWithBalance } from "./tokens/useAllTokensWithBalance";
|
|
9
|
+
export {
|
|
10
|
+
useCosmosBalance,
|
|
11
|
+
useEvmBalance,
|
|
12
|
+
useNativeTokenBalanceDestinationChain,
|
|
13
|
+
useNativeTokenBalanceFromChain,
|
|
14
|
+
} from "./tokens/useBalance";
|
|
15
|
+
export { useMultiChainBalance } from "./tokens/useMultiChainBalance";
|
|
16
|
+
export { usePrices } from "./tokens/usePrices";
|
|
17
|
+
export { useSingleTokenPrice } from "./tokens/useSingleTokenPrice";
|
|
18
|
+
export { useSquidTokens } from "./tokens/useSquidTokens";
|
|
19
|
+
export { useAllTokensWithBalanceForChain } from "./tokens/useTokensWithBalance";
|
|
20
|
+
export { useEstimate } from "./transaction/useEstimate";
|
|
21
|
+
export { useEstimatePriceImpact } from "./transaction/useEstimatePriceImpact";
|
|
22
|
+
export { useExecuteTransaction } from "./transaction/useExecuteTransaction";
|
|
23
|
+
export { useGetRoute } from "./transaction/useGetRoute";
|
|
24
|
+
export { useSingleTransaction } from "./transaction/useSingleTransaction";
|
|
25
|
+
export { useTransaction } from "./transaction/useTransaction";
|
|
26
|
+
export { useUserParams } from "./user/useUserParams";
|
|
27
|
+
export { useAutoConnect } from "./wallet/useAutoConnect";
|
|
28
|
+
export { useGnosisContext } from "./wallet/useGnosisContext";
|
|
29
|
+
export { useIntegratorContext } from "./wallet/useIntegratorContext";
|
|
30
|
+
export { useMultiChainWallet } from "./wallet/useMultiChainWallet";
|
|
31
|
+
export { useWallet } from "./wallet/useWallet";
|
|
32
|
+
export { useSquidRouter } from "./webapp-router/useSquidRouter";
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { useSquidRouter } from "@/hooks/webapp-router/useSquidRouter";
|
|
2
|
+
import type { RefObject } from "react";
|
|
3
|
+
import { useCallback, useEffect } from "react";
|
|
4
|
+
|
|
5
|
+
type Props = {
|
|
6
|
+
itemsListRef: RefObject<HTMLElement>;
|
|
7
|
+
activeListItemClassName: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const useKeyboardNavigation = (props?: Props) => {
|
|
11
|
+
const { itemsListRef, activeListItemClassName = "" } = props ?? {};
|
|
12
|
+
const { previousRoute } = useSquidRouter();
|
|
13
|
+
|
|
14
|
+
const onKeyDown = useCallback(
|
|
15
|
+
(event: any) => {
|
|
16
|
+
if (event.key === "Escape") {
|
|
17
|
+
previousRoute();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (activeListItemClassName.trim() === "") return;
|
|
22
|
+
|
|
23
|
+
const itemsList = itemsListRef?.current;
|
|
24
|
+
const separatedActiveItemClassNames = activeListItemClassName.split(" ");
|
|
25
|
+
const defaultActiveItem = itemsList?.querySelector(
|
|
26
|
+
`.${separatedActiveItemClassNames.join(".")}`
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
if (event.key === "ArrowUp") {
|
|
30
|
+
if (!itemsList) return;
|
|
31
|
+
event.preventDefault();
|
|
32
|
+
|
|
33
|
+
const activeItem = defaultActiveItem ?? itemsList.lastElementChild;
|
|
34
|
+
if (!activeItem) return;
|
|
35
|
+
|
|
36
|
+
const previousItem = activeItem.previousElementSibling;
|
|
37
|
+
if (previousItem) {
|
|
38
|
+
activeItem.classList.remove(...separatedActiveItemClassNames);
|
|
39
|
+
previousItem.classList.add(...separatedActiveItemClassNames);
|
|
40
|
+
|
|
41
|
+
// scroll to previous item
|
|
42
|
+
itemsList.scrollTo({
|
|
43
|
+
top:
|
|
44
|
+
((previousItem as HTMLLIElement).offsetTop ?? 0) -
|
|
45
|
+
itemsList.clientHeight,
|
|
46
|
+
behavior: "smooth",
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
} else if (event.key === "ArrowDown") {
|
|
50
|
+
if (!itemsList) return;
|
|
51
|
+
event.preventDefault();
|
|
52
|
+
|
|
53
|
+
const activeItem = defaultActiveItem ?? itemsList.firstElementChild;
|
|
54
|
+
if (!activeItem) return;
|
|
55
|
+
|
|
56
|
+
const nextItem = activeItem.nextElementSibling;
|
|
57
|
+
if (nextItem) {
|
|
58
|
+
activeItem.classList.remove(...separatedActiveItemClassNames);
|
|
59
|
+
nextItem.classList.add(...separatedActiveItemClassNames);
|
|
60
|
+
|
|
61
|
+
// scroll to next item
|
|
62
|
+
itemsList.scrollTo({
|
|
63
|
+
top:
|
|
64
|
+
((nextItem as HTMLLIElement).offsetTop ?? 0) -
|
|
65
|
+
itemsList.clientHeight,
|
|
66
|
+
behavior: "smooth",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
} else if (event.key === "Enter") {
|
|
70
|
+
event.preventDefault();
|
|
71
|
+
|
|
72
|
+
if (defaultActiveItem) {
|
|
73
|
+
// select active item
|
|
74
|
+
defaultActiveItem.querySelector("button")?.click();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
[previousRoute, itemsListRef, activeListItemClassName]
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
document.addEventListener("keydown", onKeyDown, false);
|
|
83
|
+
|
|
84
|
+
return () => {
|
|
85
|
+
document.removeEventListener("keydown", onKeyDown, false);
|
|
86
|
+
};
|
|
87
|
+
}, [onKeyDown]);
|
|
88
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { defaultValues } from "@/core/constants";
|
|
2
|
+
import { AppConfig } from "@/core/types/config";
|
|
3
|
+
import { WidgetRoute } from "@/core/types/route";
|
|
4
|
+
import { SwapRoute } from "@/core/types/swap";
|
|
5
|
+
import {
|
|
6
|
+
TransactionHistoryStore,
|
|
7
|
+
TransactionParams,
|
|
8
|
+
} from "@/core/types/transaction";
|
|
9
|
+
import type { Squid } from "@0xsquid/sdk";
|
|
10
|
+
import { create } from "zustand";
|
|
11
|
+
import { persist } from "zustand/middleware";
|
|
12
|
+
|
|
13
|
+
export interface SquidConfigState {
|
|
14
|
+
squid?: Squid;
|
|
15
|
+
fromPrice?: string;
|
|
16
|
+
toPrice?: number;
|
|
17
|
+
currentTransaction?: TransactionParams;
|
|
18
|
+
currentRequestId?: string;
|
|
19
|
+
config: AppConfig;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const useSquidStore = create<SquidConfigState>((_) => defaultValues);
|
|
23
|
+
|
|
24
|
+
export interface SquidRouter {
|
|
25
|
+
history: {
|
|
26
|
+
route: WidgetRoute;
|
|
27
|
+
params?: { [key: string]: any | undefined };
|
|
28
|
+
}[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const useSquidRouterStore = create<SquidRouter>((_) => ({
|
|
32
|
+
history: [
|
|
33
|
+
{
|
|
34
|
+
route: {
|
|
35
|
+
id: "swap",
|
|
36
|
+
path: "/",
|
|
37
|
+
title: "Swap",
|
|
38
|
+
headerButtons: ["settings", "history"],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Persist the store in local storage
|
|
46
|
+
* So the user can refresh the page and still see his old transactions
|
|
47
|
+
*/
|
|
48
|
+
export const usePersistStore = create(
|
|
49
|
+
persist<{
|
|
50
|
+
transactionsHistory?: TransactionHistoryStore[];
|
|
51
|
+
}>(
|
|
52
|
+
(_) => {
|
|
53
|
+
return {
|
|
54
|
+
transactionsHistory: [],
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "squid.history.store",
|
|
59
|
+
}
|
|
60
|
+
)
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
export const useSwapRoutePersistStore = create(
|
|
64
|
+
persist<{
|
|
65
|
+
swapRoute?: SwapRoute;
|
|
66
|
+
destinationAddressHasBeenUpdated?: {
|
|
67
|
+
updated: boolean;
|
|
68
|
+
filledFromWallet: boolean;
|
|
69
|
+
};
|
|
70
|
+
}>(
|
|
71
|
+
(_) => {
|
|
72
|
+
return {
|
|
73
|
+
swapRoute: undefined,
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "squid.swaproute.store",
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
);
|