wagmi-extended 0.5.0 → 0.8.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/dist/hooks/useContractWriteExtended.d.ts +1 -1
- package/dist/hooks/useERC20Approve.d.ts +28 -0
- package/dist/hooks/useFetchAssetAllowance.d.ts +250 -0
- package/dist/hooks/useToken.d.ts +179 -0
- package/dist/index.cjs.js +232 -15
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.esm.js +234 -19
- package/dist/index.esm.js.map +1 -1
- package/dist/query-config/index.d.ts +8 -0
- package/package.json +1 -1
- package/src/hooks/useContractWriteExtended.ts +1 -1
- package/src/hooks/useERC20Approve.ts +104 -0
- package/src/hooks/useFetchAssetAllowance.ts +94 -0
- package/src/hooks/useHandleTransactionMutation.ts +2 -2
- package/src/hooks/useSendTransactionExtended.ts +1 -1
- package/src/hooks/useToken.ts +122 -0
- package/src/index.ts +4 -3
- package/src/query-config/index.ts +8 -0
- package/tsconfig.json +9 -1
package/dist/index.cjs.js
CHANGED
|
@@ -2,23 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
var wagmi = require('wagmi');
|
|
4
4
|
var actions = require('wagmi/actions');
|
|
5
|
-
var reactQuery = require('@tanstack/react-query');
|
|
6
5
|
var react = require('react');
|
|
7
6
|
var viem = require('viem');
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*
|
|
12
|
-
* @returns An object with the invalidateMany function.
|
|
13
|
-
*/
|
|
14
|
-
function useInvalidateQueries() {
|
|
15
|
-
const queryClient = reactQuery.useQueryClient();
|
|
16
|
-
const invalidateMany = async (queries) => {
|
|
17
|
-
const promises = queries.map((queryKey) => queryClient.invalidateQueries({ queryKey }));
|
|
18
|
-
await Promise.all(promises);
|
|
19
|
-
};
|
|
20
|
-
return { invalidateMany };
|
|
21
|
-
}
|
|
7
|
+
var reactQuery = require('@tanstack/react-query');
|
|
8
|
+
var actions$1 = require('viem/actions');
|
|
9
|
+
var query = require('wagmi/query');
|
|
22
10
|
|
|
23
11
|
/**
|
|
24
12
|
* Default error mapping that contains a set of error identifiers mapped to user-friendly error messages.
|
|
@@ -103,6 +91,20 @@ const getParsedError = (error) => {
|
|
|
103
91
|
return message;
|
|
104
92
|
};
|
|
105
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Hook to invalidate multiple queries in the React Query cache.
|
|
96
|
+
*
|
|
97
|
+
* @returns An object with the invalidateMany function.
|
|
98
|
+
*/
|
|
99
|
+
function useInvalidateQueries() {
|
|
100
|
+
const queryClient = reactQuery.useQueryClient();
|
|
101
|
+
const invalidateMany = async (queries) => {
|
|
102
|
+
const promises = queries.map((queryKey) => queryClient.invalidateQueries({ queryKey }));
|
|
103
|
+
await Promise.all(promises);
|
|
104
|
+
};
|
|
105
|
+
return { invalidateMany };
|
|
106
|
+
}
|
|
107
|
+
|
|
106
108
|
/**
|
|
107
109
|
* Custom hook to handle transaction mutations.
|
|
108
110
|
*
|
|
@@ -243,10 +245,225 @@ function useSendTransactionExtended(settings) {
|
|
|
243
245
|
};
|
|
244
246
|
}
|
|
245
247
|
|
|
248
|
+
const queryConfig = {
|
|
249
|
+
metadataQueryConfig: {
|
|
250
|
+
staleTime: Infinity,
|
|
251
|
+
},
|
|
252
|
+
sensitiveDataQueryConfig: {
|
|
253
|
+
staleTime: 60000,
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
const EthTokenData = {
|
|
258
|
+
symbol: "ETH",
|
|
259
|
+
decimals: 18,
|
|
260
|
+
name: "Ethereum",
|
|
261
|
+
};
|
|
262
|
+
async function fetchDecimals(token, queryClient, wagmiConfig) {
|
|
263
|
+
if (token === viem.zeroAddress)
|
|
264
|
+
return EthTokenData.decimals;
|
|
265
|
+
const decimals = await queryClient.fetchQuery({
|
|
266
|
+
...query.readContractQueryOptions(wagmiConfig, {
|
|
267
|
+
address: token,
|
|
268
|
+
abi: viem.erc20Abi,
|
|
269
|
+
functionName: "decimals",
|
|
270
|
+
}),
|
|
271
|
+
...queryConfig.metadataQueryConfig,
|
|
272
|
+
});
|
|
273
|
+
return decimals;
|
|
274
|
+
}
|
|
275
|
+
async function fetchSymbol(token, queryClient, wagmiConfig) {
|
|
276
|
+
if (token === viem.zeroAddress)
|
|
277
|
+
return EthTokenData.symbol;
|
|
278
|
+
const symbol = await queryClient.fetchQuery({
|
|
279
|
+
...query.readContractQueryOptions(wagmiConfig, {
|
|
280
|
+
address: token,
|
|
281
|
+
abi: viem.erc20Abi,
|
|
282
|
+
functionName: "symbol",
|
|
283
|
+
}),
|
|
284
|
+
...queryConfig.metadataQueryConfig,
|
|
285
|
+
});
|
|
286
|
+
return symbol;
|
|
287
|
+
}
|
|
288
|
+
async function fetchName(token, queryClient, wagmiConfig) {
|
|
289
|
+
if (token === viem.zeroAddress)
|
|
290
|
+
return EthTokenData.name;
|
|
291
|
+
const name = await queryClient.fetchQuery({
|
|
292
|
+
...query.readContractQueryOptions(wagmiConfig, {
|
|
293
|
+
address: token,
|
|
294
|
+
abi: viem.erc20Abi,
|
|
295
|
+
functionName: "name",
|
|
296
|
+
}),
|
|
297
|
+
...queryConfig.metadataQueryConfig,
|
|
298
|
+
});
|
|
299
|
+
return name;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Fetches the token metadata (symbol, decimals) for the given token address.
|
|
303
|
+
* Internally calls:
|
|
304
|
+
* - `fetchSymbol(token)` to retrieve the token symbol,
|
|
305
|
+
* - `fetchDecimals(token)` to retrieve the token decimals
|
|
306
|
+
* - `fetchName(token)` to retrieve the token name
|
|
307
|
+
*
|
|
308
|
+
* @param token - The address of the token.
|
|
309
|
+
* @returns A `Token` object containing the symbol, decimals.
|
|
310
|
+
* @throws Will throw an error if symbol or decimals cannot be fetched.
|
|
311
|
+
*/
|
|
312
|
+
async function fetchToken(token, queryClient, wagmiConfig) {
|
|
313
|
+
const [symbol, decimals, name] = await Promise.all([
|
|
314
|
+
fetchSymbol(token, queryClient, wagmiConfig),
|
|
315
|
+
fetchDecimals(token, queryClient, wagmiConfig),
|
|
316
|
+
fetchName(token, queryClient, wagmiConfig),
|
|
317
|
+
]);
|
|
318
|
+
if (!symbol || !decimals) {
|
|
319
|
+
throw new Error("Failed to fetch token data");
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
symbol,
|
|
323
|
+
decimals,
|
|
324
|
+
name,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const fetchAllowance = async (asset, spender, userAddress, queryClient, config) => {
|
|
329
|
+
const [tokenData, allowance] = await Promise.all([
|
|
330
|
+
fetchToken(asset, queryClient, config),
|
|
331
|
+
actions$1.readContract(config, {
|
|
332
|
+
address: asset,
|
|
333
|
+
abi: viem.erc20Abi,
|
|
334
|
+
functionName: "allowance",
|
|
335
|
+
args: [userAddress, spender],
|
|
336
|
+
}),
|
|
337
|
+
]);
|
|
338
|
+
if (!tokenData || allowance == null) {
|
|
339
|
+
throw new Error("Failed to fetch token data or allowance");
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
bigIntValue: allowance,
|
|
343
|
+
decimals: tokenData.decimals,
|
|
344
|
+
symbol: tokenData.symbol,
|
|
345
|
+
};
|
|
346
|
+
};
|
|
347
|
+
const HookFetchAssetAllowanceQK = (asset, spender, userAddress, config, queryClient) => [
|
|
348
|
+
"hookFetchAllowance",
|
|
349
|
+
asset,
|
|
350
|
+
spender,
|
|
351
|
+
userAddress,
|
|
352
|
+
config,
|
|
353
|
+
queryClient,
|
|
354
|
+
];
|
|
355
|
+
/**
|
|
356
|
+
* Custom hook for fetching asset allowance.
|
|
357
|
+
*
|
|
358
|
+
* @param {Address} asset - The address of the ERC20 token contract.
|
|
359
|
+
* @param {Address} spender - The address of the spender to check allowance for.
|
|
360
|
+
*/
|
|
361
|
+
const useFetchAssetAllowance = ({ asset, spender, }) => {
|
|
362
|
+
const config = wagmi.useConfig();
|
|
363
|
+
const queryClient = reactQuery.useQueryClient();
|
|
364
|
+
const { address: userAddress } = wagmi.useAccount();
|
|
365
|
+
const { data, ...rest } = reactQuery.useQuery({
|
|
366
|
+
queryKey: HookFetchAssetAllowanceQK(asset, spender, userAddress, config, queryClient),
|
|
367
|
+
queryFn: () => fetchAllowance(asset, spender, userAddress, queryClient, config),
|
|
368
|
+
enabled: !!asset && !!spender && !!userAddress,
|
|
369
|
+
...queryConfig.sensitiveDataQueryConfig,
|
|
370
|
+
});
|
|
371
|
+
return {
|
|
372
|
+
...rest,
|
|
373
|
+
data,
|
|
374
|
+
queryKey: HookFetchAssetAllowanceQK(asset, spender, userAddress, config, queryClient),
|
|
375
|
+
};
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Helper function to determine human readable state of approve.
|
|
380
|
+
*
|
|
381
|
+
* @param {boolean} isApproved - Indicates if the approval is already done.
|
|
382
|
+
* @param {boolean} justApproved - Indicates if the user has just approved.
|
|
383
|
+
* @return {string} - The appropriate button text.
|
|
384
|
+
*/
|
|
385
|
+
function getApproveState(isApproved, justApproved) {
|
|
386
|
+
if (isApproved) {
|
|
387
|
+
return justApproved ? "Approve Confirmed" : "Approved";
|
|
388
|
+
}
|
|
389
|
+
return "Approve";
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Custom hook for approving ERC20 token transfers.
|
|
393
|
+
*
|
|
394
|
+
* This hook provides functionality for approving ERC20 token transfers, checking the current allowance, and handling the approval transaction using Wagmi.
|
|
395
|
+
*
|
|
396
|
+
* @param {Address} tokenAddress - The address of the ERC20 token contract.
|
|
397
|
+
* @param {Address} spenderAddress - The address of the spender to approve the transfer to.
|
|
398
|
+
* @param {bigint} [amount=BigInt(0)] - The amount of tokens to approve for transfer. Defaults to 0.
|
|
399
|
+
* @returns {Object} Object containing the following properties:
|
|
400
|
+
* - {boolean} isApproved - Indicates whether the spender is already approved to transfer the specified amount of tokens.
|
|
401
|
+
* - {boolean} isApproving - Indicates whether an approval transaction is currently pending.
|
|
402
|
+
* - {Function} approveAsync - Function to trigger the approval transaction.
|
|
403
|
+
*/
|
|
404
|
+
const useERC20Approve = (tokenAddress, spenderAddress, amount) => {
|
|
405
|
+
const [isApproved, setIsApproved] = react.useState(false);
|
|
406
|
+
const [justApproved, setJustApproved] = react.useState(false);
|
|
407
|
+
const { data: allowance, queryKey } = useFetchAssetAllowance({
|
|
408
|
+
asset: tokenAddress,
|
|
409
|
+
spender: spenderAddress,
|
|
410
|
+
});
|
|
411
|
+
const { writeContractAsync: approveTokenAsync, isPending } = useContractWriteExtended({
|
|
412
|
+
queriesToInvalidate: [queryKey],
|
|
413
|
+
});
|
|
414
|
+
react.useEffect(() => {
|
|
415
|
+
if (amount == null) {
|
|
416
|
+
setIsApproved(false);
|
|
417
|
+
}
|
|
418
|
+
else if (allowance && allowance.bigIntValue >= amount) {
|
|
419
|
+
setIsApproved(true);
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
setIsApproved(false);
|
|
423
|
+
}
|
|
424
|
+
}, [allowance, amount]);
|
|
425
|
+
const approveAsync = async () => {
|
|
426
|
+
const amountToApprove = amount;
|
|
427
|
+
if (!spenderAddress) {
|
|
428
|
+
throw new Error("spenderAddress is undefined!");
|
|
429
|
+
}
|
|
430
|
+
if (!tokenAddress) {
|
|
431
|
+
throw new Error("tokenAddress is undefined!");
|
|
432
|
+
}
|
|
433
|
+
if (amountToApprove == null) {
|
|
434
|
+
throw new Error("amountToApprove is undefined!");
|
|
435
|
+
}
|
|
436
|
+
try {
|
|
437
|
+
await approveTokenAsync({
|
|
438
|
+
address: tokenAddress,
|
|
439
|
+
abi: viem.erc20Abi,
|
|
440
|
+
functionName: "approve",
|
|
441
|
+
args: [spenderAddress, amountToApprove],
|
|
442
|
+
}, {
|
|
443
|
+
onSuccess: () => {
|
|
444
|
+
setJustApproved(true);
|
|
445
|
+
},
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
catch (e) {
|
|
449
|
+
console.error("Error approving token:", e);
|
|
450
|
+
throw e;
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
return {
|
|
454
|
+
isApproved,
|
|
455
|
+
isApproving: isPending,
|
|
456
|
+
justApproved,
|
|
457
|
+
approveAsync,
|
|
458
|
+
};
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
exports.getApproveState = getApproveState;
|
|
246
462
|
exports.getErrorMapping = getErrorMapping;
|
|
247
463
|
exports.getParsedError = getParsedError;
|
|
248
464
|
exports.resetErrorMapping = resetErrorMapping;
|
|
249
465
|
exports.setErrorMapping = setErrorMapping;
|
|
250
466
|
exports.useContractWriteExtended = useContractWriteExtended;
|
|
467
|
+
exports.useERC20Approve = useERC20Approve;
|
|
251
468
|
exports.useSendTransactionExtended = useSendTransactionExtended;
|
|
252
469
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/hooks/useInvalidateQueries.ts","../src/utils/errorParser.ts","../src/hooks/useHandleTransactionMutation.ts","../src/hooks/useContractWriteExtended.ts","../src/hooks/useSendTransactionExtended.ts"],"sourcesContent":["import { QueryKey, useQueryClient } from \"@tanstack/react-query\";\n\n/**\n * Hook to invalidate multiple queries in the React Query cache.\n *\n * @returns An object with the invalidateMany function.\n */\nexport function useInvalidateQueries() {\n const queryClient = useQueryClient();\n\n const invalidateMany = async (queries: (QueryKey | undefined)[]) => {\n const promises = queries.map((queryKey) =>\n queryClient.invalidateQueries({ queryKey })\n );\n await Promise.all(promises);\n };\n\n return { invalidateMany };\n}\n","import { BaseError, ContractFunctionRevertedError } from \"viem\";\n\n/**\n * Default error mapping that contains a set of error identifiers mapped to user-friendly error messages.\n */\nconst defaultErrorMapping: Record<string, string> = {\n EnforcedPause: \"Temporary pause in effect, please check Discord for updates.\",\n ErrorNotEnoughAllowance:\n \"Not enough allowance, did you approve your tokens first?\",\n \"0xc2139725\": \"Not enough allowance, did you approve your tokens first?\",\n SharesReceivedBelowMinimum:\n \"Action exceeded safe slippage parameters, please try again later\",\n \"0xea8d7f02\":\n \"Action exceeded safe slippage parameters, please try again later\",\n MaxSlippageExceeded:\n \"Action exceeded safe slippage parameters, please try again later\",\n \"51\": \"Supply cap exceeded\",\n};\n\n/**\n * A mutable copy of the default error mapping that can be extended or overridden by users.\n */\nlet currentErrorMapping: Record<string, string> = { ...defaultErrorMapping };\n\n/**\n * Merges a custom error mapping into the current error mapping.\n * Custom values override any existing keys.\n *\n * @param customMapping - An object containing error keys and the corresponding custom messages.\n *\n * @example\n * setErrorMapping({\n * ErrorNotEnoughAllowance: \"Custom message: Please approve tokens first!\",\n * NewCustomError: \"A custom error occurred.\"\n * });\n */\nexport const setErrorMapping = (\n customMapping: Record<string, string>\n): void => {\n currentErrorMapping = { ...currentErrorMapping, ...customMapping };\n};\n\n/**\n * Resets the current error mapping to the default error mapping.\n *\n * @example\n * resetErrorMapping();\n */\nexport const resetErrorMapping = (): void => {\n currentErrorMapping = { ...defaultErrorMapping };\n};\n\n/**\n * Retrieves the current error mapping.\n *\n * @returns The current error mapping object.\n *\n * @example\n * const mapping = getErrorMapping();\n * console.log(mapping);\n */\nexport const getErrorMapping = (): Record<string, string> =>\n currentErrorMapping;\n\n/**\n * Parses an error object and returns a user-friendly error message.\n *\n * The function checks if the error is a ContractFunctionRevertedError by attempting to walk through\n * the error using its `walk` method. If a matching error is found and its error key exists in the\n * current error mapping, the corresponding custom message will be returned. Otherwise, it falls back\n * to the error's own message properties.\n *\n * @param error - The error object, potentially including additional error details.\n * @returns A user-friendly error message.\n *\n * @example\n * const message = getParsedError(someError);\n * console.log(message); // Outputs a custom error message or a default error message.\n */\nexport const getParsedError = (error: any | BaseError): string => {\n const defaultMessage = \"An unknown error occurred. Please contact support.\";\n let message = defaultMessage;\n let errorKey = \"\";\n\n const revertedError = error?.walk\n ? error.walk((err: unknown) => err instanceof ContractFunctionRevertedError)\n : null;\n if (revertedError instanceof ContractFunctionRevertedError) {\n errorKey =\n revertedError.data?.errorName ??\n revertedError.signature ??\n revertedError.reason ??\n \"\";\n if (currentErrorMapping[errorKey]) return currentErrorMapping[errorKey];\n }\n\n message = error.shortMessage || error.details || error.message || message;\n return message;\n};\n","import { waitForTransactionReceipt } from \"wagmi/actions\";\nimport { useInvalidateQueries } from \"./useInvalidateQueries\";\nimport { useConfig } from \"wagmi\";\nimport { QueryKey } from \"@tanstack/query-core\";\nimport { Address } from \"viem\";\nimport { useState } from \"react\";\nimport { getParsedError } from \"../utils/errorParser\";\n\nexport type WriteExtendedAsyncParams = {\n onSuccess?: (txHash: Address) => void;\n onError?: (e: any) => void;\n onSettled?: () => void;\n queriesToInvalidate?: (QueryKey | undefined)[];\n disableLogging?: boolean;\n disableWaitingForReceipt?: boolean;\n};\n\n/**\n * Custom hook to handle transaction mutations.\n *\n * @returns {Function} A shared `onSettled` callback for transaction mutations.\n */\nexport function useHandleTransactionMutation({\n settings,\n}: {\n settings?: WriteExtendedAsyncParams;\n}) {\n const wagmiConfig = useConfig();\n\n const { invalidateMany } = useInvalidateQueries();\n const [isPending, setIsPending] = useState(false);\n const [errorMessage, setErrorMessage] = useState<string | undefined>(\n undefined\n );\n\n const onMutate = () => {\n setIsPending(true);\n setErrorMessage(undefined);\n };\n\n const onSettled = async (\n txHash: Address | undefined,\n error: any,\n args: any\n ) => {\n try {\n if (error) throw error;\n\n if (!settings?.disableWaitingForReceipt) {\n // 1. wait for transaction receipt\n const txReceipt = await waitForTransactionReceipt(wagmiConfig, {\n hash: txHash!,\n });\n\n // 2. throw if receipt is not valid\n if (txReceipt.status === \"reverted\")\n throw new Error(\"Execution reverted.\");\n if (txReceipt.status !== \"success\")\n throw new Error(\"Execution reverted.\");\n }\n\n // 3. invalidate queries\n if (settings?.queriesToInvalidate)\n await invalidateMany(settings?.queriesToInvalidate);\n\n // 4. call onSuccess callback\n settings?.onSuccess?.(txHash!);\n\n if (!settings?.disableLogging) {\n // 5. log result\n // eslint-disable-next-line no-console\n console.info(\"Operation successful:\", txHash); // todo: add logging service\n }\n // 6. return result\n return txHash;\n } catch (error) {\n const parsedError = getParsedError(error);\n\n if (!settings?.disableLogging) {\n // 1. log error\n console.error(\n `ContractWriteExtended Operation failed with error(parsed): ${parsedError}`,\n { error },\n { args }\n );\n console.error({ error });\n }\n // 2. set error message\n setErrorMessage(parsedError);\n\n // 3. call callback\n settings?.onError?.(error);\n } finally {\n setIsPending(false);\n // 1. call callback\n settings?.onSettled?.();\n }\n return undefined;\n };\n\n return {\n onMutate,\n onSettled,\n isPending,\n errorMessage,\n };\n}\n","import { useWriteContract } from \"wagmi\";\nimport {\n WriteExtendedAsyncParams,\n useHandleTransactionMutation,\n} from \"./useHandleTransactionMutation\";\n\n/**\n * Custom hook for writing to a smart contract using Wagmi.\n *\n * This hook provides functionality for sending a transaction using Wagmi, handling the asynchronous nature of the operation, waiting for the transaction receipt, and error handling.\n *\n * @param {WriteExtendedAsyncParams} [settings] - Optional settings for the write operation.\n * @param {boolean} [settings.disableWaitingForReceipt] - Disables waiting for the transaction receipt.\n * @param {boolean} [settings.disableLogging] - Disables logging the result of the transaction.\n * @param {Function} [settings.onSuccess] - Callback function to be called on successful transaction.\n * @param {Function} [settings.onError] - Callback function to be called on transaction error.\n * @param {Function} [settings.onSettled] - Callback function to be called after the transaction settles (whether success or failure).\n * @param {QueryKey[]} [settings.queriesToInvalidate] - Array of query keys to invalidate after the transaction receives a receipt.\n * @returns {Object} Object containing the following properties:\n * - {boolean} isPending - Indicates whether the transaction is pending.\n * - {string|undefined} errorMessage - The error message, if an error occurred during the transaction.\n * - {Function} writeContractAsync - Function to trigger the write operation.\n */\n\nexport function useContractWriteExtended(settings?: WriteExtendedAsyncParams) {\n const { isPending, errorMessage, onMutate, onSettled } =\n useHandleTransactionMutation({\n settings,\n });\n\n const { writeContractAsync, ...rest } = useWriteContract({\n mutation: {\n onMutate,\n onSettled,\n },\n });\n\n return {\n ...rest,\n isPending,\n errorMessage,\n writeContractAsync,\n };\n}\n","import { Hash } from \"viem\";\nimport { useSendTransaction } from \"wagmi\";\nimport { QueryKey } from \"@tanstack/query-core\";\nimport { useHandleTransactionMutation } from \"./useHandleTransactionMutation\";\n\nexport type SeamlessSendAsyncParams = {\n onSuccess?: (txHash: Hash) => void;\n onError?: (e: any) => void;\n onSettled?: () => void;\n queriesToInvalidate?: (QueryKey | undefined)[];\n};\n\n/**\n * Custom hook for sending a transaction using Wagmi.\n *\n * This hook provides functionality for sending a transaction using Wagmi, handling the asynchronous nature of the operation, waiting for the transaction receipt, and error handling.\n *\n * @param {SeamlessWriteAsyncParams} [settings] - Optional settings for the write operation.\n * @param {boolean} [settings.disableWaitingForReceipt] - Disables waiting for the transaction receipt.\n * @param {boolean} [settings.disableLogging] - Disables logging the result of the transaction.\n * @param {Function} [settings.onSuccess] - Callback function to be called on successful transaction.\n * @param {Function} [settings.onError] - Callback function to be called on transaction error.\n * @param {Function} [settings.onSettled] - Callback function to be called after the transaction settles (whether success or failure).\n * @param {QueryKey[]} [settings.queriesToInvalidate] - Array of query keys to invalidate after the transaction receives a receipt.\n * @returns {Object} Object containing the following properties:\n * - {boolean} isPending - Indicates whether the transaction is pending.\n * - {string|undefined} errorMessage - The error message, if an error occurred during the transaction.\n * - {Function} sendTransactionAsync - Function to trigger the send transaction mutation.\n */\n\nexport function useSendTransactionExtended(settings?: SeamlessSendAsyncParams) {\n const { isPending, errorMessage, onMutate, onSettled } =\n useHandleTransactionMutation({\n settings,\n });\n\n const { sendTransactionAsync, ...rest } = useSendTransaction({\n mutation: {\n onMutate,\n onSettled,\n },\n });\n\n return {\n ...rest,\n isPending,\n errorMessage,\n sendTransactionAsync,\n };\n}\n"],"names":["useQueryClient","ContractFunctionRevertedError","useConfig","useState","waitForTransactionReceipt","useWriteContract","useSendTransaction"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/utils/errorParser.ts","../src/hooks/useInvalidateQueries.ts","../src/hooks/useHandleTransactionMutation.ts","../src/hooks/useContractWriteExtended.ts","../src/hooks/useSendTransactionExtended.ts","../src/query-config/index.ts","../src/hooks/useToken.ts","../src/hooks/useFetchAssetAllowance.ts","../src/hooks/useERC20Approve.ts"],"sourcesContent":["import { BaseError, ContractFunctionRevertedError } from \"viem\";\n\n/**\n * Default error mapping that contains a set of error identifiers mapped to user-friendly error messages.\n */\nconst defaultErrorMapping: Record<string, string> = {\n EnforcedPause: \"Temporary pause in effect, please check Discord for updates.\",\n ErrorNotEnoughAllowance:\n \"Not enough allowance, did you approve your tokens first?\",\n \"0xc2139725\": \"Not enough allowance, did you approve your tokens first?\",\n SharesReceivedBelowMinimum:\n \"Action exceeded safe slippage parameters, please try again later\",\n \"0xea8d7f02\":\n \"Action exceeded safe slippage parameters, please try again later\",\n MaxSlippageExceeded:\n \"Action exceeded safe slippage parameters, please try again later\",\n \"51\": \"Supply cap exceeded\",\n};\n\n/**\n * A mutable copy of the default error mapping that can be extended or overridden by users.\n */\nlet currentErrorMapping: Record<string, string> = { ...defaultErrorMapping };\n\n/**\n * Merges a custom error mapping into the current error mapping.\n * Custom values override any existing keys.\n *\n * @param customMapping - An object containing error keys and the corresponding custom messages.\n *\n * @example\n * setErrorMapping({\n * ErrorNotEnoughAllowance: \"Custom message: Please approve tokens first!\",\n * NewCustomError: \"A custom error occurred.\"\n * });\n */\nexport const setErrorMapping = (\n customMapping: Record<string, string>\n): void => {\n currentErrorMapping = { ...currentErrorMapping, ...customMapping };\n};\n\n/**\n * Resets the current error mapping to the default error mapping.\n *\n * @example\n * resetErrorMapping();\n */\nexport const resetErrorMapping = (): void => {\n currentErrorMapping = { ...defaultErrorMapping };\n};\n\n/**\n * Retrieves the current error mapping.\n *\n * @returns The current error mapping object.\n *\n * @example\n * const mapping = getErrorMapping();\n * console.log(mapping);\n */\nexport const getErrorMapping = (): Record<string, string> =>\n currentErrorMapping;\n\n/**\n * Parses an error object and returns a user-friendly error message.\n *\n * The function checks if the error is a ContractFunctionRevertedError by attempting to walk through\n * the error using its `walk` method. If a matching error is found and its error key exists in the\n * current error mapping, the corresponding custom message will be returned. Otherwise, it falls back\n * to the error's own message properties.\n *\n * @param error - The error object, potentially including additional error details.\n * @returns A user-friendly error message.\n *\n * @example\n * const message = getParsedError(someError);\n * console.log(message); // Outputs a custom error message or a default error message.\n */\nexport const getParsedError = (error: any | BaseError): string => {\n const defaultMessage = \"An unknown error occurred. Please contact support.\";\n let message = defaultMessage;\n let errorKey = \"\";\n\n const revertedError = error?.walk\n ? error.walk((err: unknown) => err instanceof ContractFunctionRevertedError)\n : null;\n if (revertedError instanceof ContractFunctionRevertedError) {\n errorKey =\n revertedError.data?.errorName ??\n revertedError.signature ??\n revertedError.reason ??\n \"\";\n if (currentErrorMapping[errorKey]) return currentErrorMapping[errorKey];\n }\n\n message = error.shortMessage || error.details || error.message || message;\n return message;\n};\n","import { QueryKey, useQueryClient } from \"@tanstack/react-query\";\n\n/**\n * Hook to invalidate multiple queries in the React Query cache.\n *\n * @returns An object with the invalidateMany function.\n */\nexport function useInvalidateQueries() {\n const queryClient = useQueryClient();\n\n const invalidateMany = async (queries: (QueryKey | undefined)[]) => {\n const promises = queries.map((queryKey) =>\n queryClient.invalidateQueries({ queryKey })\n );\n await Promise.all(promises);\n };\n\n return { invalidateMany };\n}\n","import { waitForTransactionReceipt } from \"wagmi/actions\";\nimport { useConfig } from \"wagmi\";\nimport { QueryKey } from \"@tanstack/query-core\";\nimport { Address } from \"viem\";\nimport { useState } from \"react\";\nimport { getParsedError } from \"../utils/errorParser.js\";\nimport { useInvalidateQueries } from \"./useInvalidateQueries.js\";\n\nexport type WriteExtendedAsyncParams = {\n onSuccess?: (txHash: Address) => void;\n onError?: (e: any) => void;\n onSettled?: () => void;\n queriesToInvalidate?: (QueryKey | undefined)[];\n disableLogging?: boolean;\n disableWaitingForReceipt?: boolean;\n};\n\n/**\n * Custom hook to handle transaction mutations.\n *\n * @returns {Function} A shared `onSettled` callback for transaction mutations.\n */\nexport function useHandleTransactionMutation({\n settings,\n}: {\n settings?: WriteExtendedAsyncParams;\n}) {\n const wagmiConfig = useConfig();\n\n const { invalidateMany } = useInvalidateQueries();\n const [isPending, setIsPending] = useState(false);\n const [errorMessage, setErrorMessage] = useState<string | undefined>(\n undefined\n );\n\n const onMutate = () => {\n setIsPending(true);\n setErrorMessage(undefined);\n };\n\n const onSettled = async (\n txHash: Address | undefined,\n error: any,\n args: any\n ) => {\n try {\n if (error) throw error;\n\n if (!settings?.disableWaitingForReceipt) {\n // 1. wait for transaction receipt\n const txReceipt = await waitForTransactionReceipt(wagmiConfig, {\n hash: txHash!,\n });\n\n // 2. throw if receipt is not valid\n if (txReceipt.status === \"reverted\")\n throw new Error(\"Execution reverted.\");\n if (txReceipt.status !== \"success\")\n throw new Error(\"Execution reverted.\");\n }\n\n // 3. invalidate queries\n if (settings?.queriesToInvalidate)\n await invalidateMany(settings?.queriesToInvalidate);\n\n // 4. call onSuccess callback\n settings?.onSuccess?.(txHash!);\n\n if (!settings?.disableLogging) {\n // 5. log result\n // eslint-disable-next-line no-console\n console.info(\"Operation successful:\", txHash); // todo: add logging service\n }\n // 6. return result\n return txHash;\n } catch (error) {\n const parsedError = getParsedError(error);\n\n if (!settings?.disableLogging) {\n // 1. log error\n console.error(\n `ContractWriteExtended Operation failed with error(parsed): ${parsedError}`,\n { error },\n { args }\n );\n console.error({ error });\n }\n // 2. set error message\n setErrorMessage(parsedError);\n\n // 3. call callback\n settings?.onError?.(error);\n } finally {\n setIsPending(false);\n // 1. call callback\n settings?.onSettled?.();\n }\n return undefined;\n };\n\n return {\n onMutate,\n onSettled,\n isPending,\n errorMessage,\n };\n}\n","import { useWriteContract } from \"wagmi\";\nimport {\n WriteExtendedAsyncParams,\n useHandleTransactionMutation,\n} from \"./useHandleTransactionMutation.js\";\n\n/**\n * Custom hook for writing to a smart contract using Wagmi.\n *\n * This hook provides functionality for sending a transaction using Wagmi, handling the asynchronous nature of the operation, waiting for the transaction receipt, and error handling.\n *\n * @param {WriteExtendedAsyncParams} [settings] - Optional settings for the write operation.\n * @param {boolean} [settings.disableWaitingForReceipt] - Disables waiting for the transaction receipt.\n * @param {boolean} [settings.disableLogging] - Disables logging the result of the transaction.\n * @param {Function} [settings.onSuccess] - Callback function to be called on successful transaction.\n * @param {Function} [settings.onError] - Callback function to be called on transaction error.\n * @param {Function} [settings.onSettled] - Callback function to be called after the transaction settles (whether success or failure).\n * @param {QueryKey[]} [settings.queriesToInvalidate] - Array of query keys to invalidate after the transaction receives a receipt.\n * @returns {Object} Object containing the following properties:\n * - {boolean} isPending - Indicates whether the transaction is pending.\n * - {string|undefined} errorMessage - The error message, if an error occurred during the transaction.\n * - {Function} writeContractAsync - Function to trigger the write operation.\n */\n\nexport function useContractWriteExtended(settings?: WriteExtendedAsyncParams) {\n const { isPending, errorMessage, onMutate, onSettled } =\n useHandleTransactionMutation({\n settings,\n });\n\n const { writeContractAsync, ...rest } = useWriteContract({\n mutation: {\n onMutate,\n onSettled,\n },\n });\n\n return {\n ...rest,\n isPending,\n errorMessage,\n writeContractAsync,\n };\n}\n","import { Hash } from \"viem\";\nimport { useSendTransaction } from \"wagmi\";\nimport { QueryKey } from \"@tanstack/query-core\";\nimport { useHandleTransactionMutation } from \"./useHandleTransactionMutation.js\";\n\nexport type SeamlessSendAsyncParams = {\n onSuccess?: (txHash: Hash) => void;\n onError?: (e: any) => void;\n onSettled?: () => void;\n queriesToInvalidate?: (QueryKey | undefined)[];\n};\n\n/**\n * Custom hook for sending a transaction using Wagmi.\n *\n * This hook provides functionality for sending a transaction using Wagmi, handling the asynchronous nature of the operation, waiting for the transaction receipt, and error handling.\n *\n * @param {SeamlessWriteAsyncParams} [settings] - Optional settings for the write operation.\n * @param {boolean} [settings.disableWaitingForReceipt] - Disables waiting for the transaction receipt.\n * @param {boolean} [settings.disableLogging] - Disables logging the result of the transaction.\n * @param {Function} [settings.onSuccess] - Callback function to be called on successful transaction.\n * @param {Function} [settings.onError] - Callback function to be called on transaction error.\n * @param {Function} [settings.onSettled] - Callback function to be called after the transaction settles (whether success or failure).\n * @param {QueryKey[]} [settings.queriesToInvalidate] - Array of query keys to invalidate after the transaction receives a receipt.\n * @returns {Object} Object containing the following properties:\n * - {boolean} isPending - Indicates whether the transaction is pending.\n * - {string|undefined} errorMessage - The error message, if an error occurred during the transaction.\n * - {Function} sendTransactionAsync - Function to trigger the send transaction mutation.\n */\n\nexport function useSendTransactionExtended(settings?: SeamlessSendAsyncParams) {\n const { isPending, errorMessage, onMutate, onSettled } =\n useHandleTransactionMutation({\n settings,\n });\n\n const { sendTransactionAsync, ...rest } = useSendTransaction({\n mutation: {\n onMutate,\n onSettled,\n },\n });\n\n return {\n ...rest,\n isPending,\n errorMessage,\n sendTransactionAsync,\n };\n}\n","export const queryConfig = {\n metadataQueryConfig: {\n staleTime: Infinity,\n },\n sensitiveDataQueryConfig: {\n staleTime: 60_000,\n },\n};\n","import { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { readContractQueryOptions } from \"wagmi/query\";\nimport { Address, zeroAddress, erc20Abi } from \"viem\";\nimport { queryConfig } from \"../query-config/index.js\";\nimport { useConfig } from \"wagmi\";\n\nexport interface Token {\n symbol: string;\n decimals: number;\n name: string;\n}\n\nexport const EthTokenData: Token = {\n symbol: \"ETH\",\n decimals: 18,\n name: \"Ethereum\",\n};\n\nexport async function fetchDecimals(\n token: Address,\n queryClient: any,\n wagmiConfig: any\n): Promise<number | undefined> {\n if (token === zeroAddress) return EthTokenData.decimals;\n\n const decimals = await queryClient.fetchQuery({\n ...readContractQueryOptions(wagmiConfig, {\n address: token,\n abi: erc20Abi,\n functionName: \"decimals\",\n }),\n ...queryConfig.metadataQueryConfig,\n });\n\n return decimals;\n}\n\nexport async function fetchSymbol(\n token: Address,\n queryClient: any,\n wagmiConfig: any\n): Promise<string> {\n if (token === zeroAddress) return EthTokenData.symbol;\n\n const symbol = await queryClient.fetchQuery({\n ...readContractQueryOptions(wagmiConfig, {\n address: token,\n abi: erc20Abi,\n functionName: \"symbol\",\n }),\n ...queryConfig.metadataQueryConfig,\n });\n\n return symbol;\n}\n\nexport async function fetchName(\n token: Address,\n queryClient: any,\n wagmiConfig: any\n): Promise<string> {\n if (token === zeroAddress) return EthTokenData.name;\n\n const name = await queryClient.fetchQuery({\n ...readContractQueryOptions(wagmiConfig, {\n address: token,\n abi: erc20Abi,\n functionName: \"name\",\n }),\n ...queryConfig.metadataQueryConfig,\n });\n\n return name;\n}\n\n/**\n * Fetches the token metadata (symbol, decimals) for the given token address.\n * Internally calls:\n * - `fetchSymbol(token)` to retrieve the token symbol,\n * - `fetchDecimals(token)` to retrieve the token decimals\n * - `fetchName(token)` to retrieve the token name\n *\n * @param token - The address of the token.\n * @returns A `Token` object containing the symbol, decimals.\n * @throws Will throw an error if symbol or decimals cannot be fetched.\n */\nexport async function fetchToken(\n token: Address,\n queryClient: any,\n wagmiConfig: any\n): Promise<Token> {\n const [symbol, decimals, name] = await Promise.all([\n fetchSymbol(token, queryClient, wagmiConfig),\n fetchDecimals(token, queryClient, wagmiConfig),\n fetchName(token, queryClient, wagmiConfig),\n ]);\n if (!symbol || !decimals) {\n throw new Error(\"Failed to fetch token data\");\n }\n\n return {\n symbol,\n decimals,\n name,\n };\n}\n\nexport const useToken = (asset?: Address) => {\n const queryClient = useQueryClient();\n const config = useConfig();\n\n const { data, ...rest } = useQuery({\n queryKey: [\"useTokenWagmiExtended\", asset],\n queryFn: () => fetchToken(asset!, queryClient, config),\n enabled: Boolean(asset),\n });\n\n return {\n ...rest,\n data,\n };\n};\n","import { useQuery, useQueryClient } from \"@tanstack/react-query\";\nimport { Address, erc20Abi } from \"viem\";\nimport { readContract } from \"viem/actions\";\nimport { useAccount, useConfig } from \"wagmi\";\nimport { fetchToken } from \"./useToken.js\";\nimport { queryConfig } from \"../query-config/index.js\";\n\nexport const fetchAllowance = async (\n asset: Address,\n spender: Address,\n userAddress: Address,\n queryClient: any,\n config: any\n) => {\n const [tokenData, allowance] = await Promise.all([\n fetchToken(asset, queryClient, config),\n readContract(config, {\n address: asset,\n abi: erc20Abi,\n functionName: \"allowance\",\n args: [userAddress, spender],\n }),\n ]);\n\n if (!tokenData || allowance == null) {\n throw new Error(\"Failed to fetch token data or allowance\");\n }\n\n return {\n bigIntValue: allowance,\n decimals: tokenData.decimals,\n symbol: tokenData.symbol,\n };\n};\n\nconst HookFetchAssetAllowanceQK = (\n asset: Address,\n spender: Address,\n userAddress: Address,\n config: any,\n queryClient: any\n) =>\n [\n \"hookFetchAllowance\",\n asset,\n spender,\n userAddress,\n config,\n queryClient,\n ] as const;\n\n/**\n * Custom hook for fetching asset allowance.\n *\n * @param {Address} asset - The address of the ERC20 token contract.\n * @param {Address} spender - The address of the spender to check allowance for.\n */\nexport const useFetchAssetAllowance = ({\n asset,\n spender,\n}: {\n asset?: Address;\n spender?: Address;\n}) => {\n const config = useConfig();\n const queryClient = useQueryClient();\n const { address: userAddress } = useAccount();\n\n const { data, ...rest } = useQuery({\n queryKey: HookFetchAssetAllowanceQK(\n asset!,\n spender!,\n userAddress!,\n config,\n queryClient\n ),\n queryFn: () =>\n fetchAllowance(asset!, spender!, userAddress!, queryClient, config),\n enabled: !!asset && !!spender && !!userAddress,\n ...queryConfig.sensitiveDataQueryConfig,\n });\n\n return {\n ...rest,\n data,\n queryKey: HookFetchAssetAllowanceQK(\n asset!,\n spender!,\n userAddress!,\n config,\n queryClient\n ),\n };\n};\n","import { useState, useEffect } from \"react\";\nimport { Address, maxUint256, erc20Abi } from \"viem\";\nimport { useFetchAssetAllowance } from \"./useFetchAssetAllowance.js\";\nimport { useContractWriteExtended } from \"./useContractWriteExtended.js\";\n\nconst ALWAYS_APPROVE_MAX = false;\n\n/**\n * Helper function to determine human readable state of approve.\n *\n * @param {boolean} isApproved - Indicates if the approval is already done.\n * @param {boolean} justApproved - Indicates if the user has just approved.\n * @return {string} - The appropriate button text.\n */\n\nexport function getApproveState(isApproved?: boolean, justApproved?: boolean) {\n if (isApproved) {\n return justApproved ? \"Approve Confirmed\" : \"Approved\";\n }\n return \"Approve\";\n}\n\n/**\n * Custom hook for approving ERC20 token transfers.\n *\n * This hook provides functionality for approving ERC20 token transfers, checking the current allowance, and handling the approval transaction using Wagmi.\n *\n * @param {Address} tokenAddress - The address of the ERC20 token contract.\n * @param {Address} spenderAddress - The address of the spender to approve the transfer to.\n * @param {bigint} [amount=BigInt(0)] - The amount of tokens to approve for transfer. Defaults to 0.\n * @returns {Object} Object containing the following properties:\n * - {boolean} isApproved - Indicates whether the spender is already approved to transfer the specified amount of tokens.\n * - {boolean} isApproving - Indicates whether an approval transaction is currently pending.\n * - {Function} approveAsync - Function to trigger the approval transaction.\n */\n\nexport const useERC20Approve = (\n tokenAddress?: Address,\n spenderAddress?: Address,\n amount?: bigint\n) => {\n const [isApproved, setIsApproved] = useState(false);\n const [justApproved, setJustApproved] = useState(false);\n\n const { data: allowance, queryKey } = useFetchAssetAllowance({\n asset: tokenAddress,\n spender: spenderAddress,\n });\n\n const { writeContractAsync: approveTokenAsync, isPending } =\n useContractWriteExtended({\n queriesToInvalidate: [queryKey],\n });\n\n useEffect(() => {\n if (amount == null) {\n setIsApproved(false);\n } else if (allowance && allowance.bigIntValue >= amount) {\n setIsApproved(true);\n } else {\n setIsApproved(false);\n }\n }, [allowance, amount]);\n\n const approveAsync = async () => {\n const amountToApprove = ALWAYS_APPROVE_MAX ? maxUint256 : amount;\n\n if (!spenderAddress) {\n throw new Error(\"spenderAddress is undefined!\");\n }\n if (!tokenAddress) {\n throw new Error(\"tokenAddress is undefined!\");\n }\n if (amountToApprove == null) {\n throw new Error(\"amountToApprove is undefined!\");\n }\n\n try {\n await approveTokenAsync(\n {\n address: tokenAddress,\n abi: erc20Abi,\n functionName: \"approve\",\n args: [spenderAddress, amountToApprove],\n },\n {\n onSuccess: () => {\n setJustApproved(true);\n },\n }\n );\n } catch (e: any) {\n console.error(\"Error approving token:\", e);\n throw e;\n }\n };\n\n return {\n isApproved,\n isApproving: isPending,\n justApproved,\n approveAsync,\n };\n};\n"],"names":["ContractFunctionRevertedError","useQueryClient","useConfig","useState","waitForTransactionReceipt","useWriteContract","useSendTransaction","zeroAddress","readContractQueryOptions","erc20Abi","readContract","useAccount","useQuery","useEffect"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export * from "./hooks/useContractWriteExtended";
|
|
2
|
-
export * from "./hooks/useSendTransactionExtended";
|
|
3
|
-
export * from "./
|
|
1
|
+
export * from "./hooks/useContractWriteExtended.js";
|
|
2
|
+
export * from "./hooks/useSendTransactionExtended.js";
|
|
3
|
+
export * from "./hooks/useERC20Approve.js";
|
|
4
|
+
export * from "./utils/errorParser.js";
|
package/dist/index.esm.js
CHANGED
|
@@ -1,22 +1,10 @@
|
|
|
1
|
-
import { useConfig, useWriteContract, useSendTransaction } from 'wagmi';
|
|
1
|
+
import { useConfig, useWriteContract, useSendTransaction, useAccount } from 'wagmi';
|
|
2
2
|
import { waitForTransactionReceipt } from 'wagmi/actions';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* Hook to invalidate multiple queries in the React Query cache.
|
|
9
|
-
*
|
|
10
|
-
* @returns An object with the invalidateMany function.
|
|
11
|
-
*/
|
|
12
|
-
function useInvalidateQueries() {
|
|
13
|
-
const queryClient = useQueryClient();
|
|
14
|
-
const invalidateMany = async (queries) => {
|
|
15
|
-
const promises = queries.map((queryKey) => queryClient.invalidateQueries({ queryKey }));
|
|
16
|
-
await Promise.all(promises);
|
|
17
|
-
};
|
|
18
|
-
return { invalidateMany };
|
|
19
|
-
}
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { ContractFunctionRevertedError, zeroAddress, erc20Abi } from 'viem';
|
|
5
|
+
import { useQueryClient, useQuery } from '@tanstack/react-query';
|
|
6
|
+
import { readContract } from 'viem/actions';
|
|
7
|
+
import { readContractQueryOptions } from 'wagmi/query';
|
|
20
8
|
|
|
21
9
|
/**
|
|
22
10
|
* Default error mapping that contains a set of error identifiers mapped to user-friendly error messages.
|
|
@@ -101,6 +89,20 @@ const getParsedError = (error) => {
|
|
|
101
89
|
return message;
|
|
102
90
|
};
|
|
103
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Hook to invalidate multiple queries in the React Query cache.
|
|
94
|
+
*
|
|
95
|
+
* @returns An object with the invalidateMany function.
|
|
96
|
+
*/
|
|
97
|
+
function useInvalidateQueries() {
|
|
98
|
+
const queryClient = useQueryClient();
|
|
99
|
+
const invalidateMany = async (queries) => {
|
|
100
|
+
const promises = queries.map((queryKey) => queryClient.invalidateQueries({ queryKey }));
|
|
101
|
+
await Promise.all(promises);
|
|
102
|
+
};
|
|
103
|
+
return { invalidateMany };
|
|
104
|
+
}
|
|
105
|
+
|
|
104
106
|
/**
|
|
105
107
|
* Custom hook to handle transaction mutations.
|
|
106
108
|
*
|
|
@@ -241,5 +243,218 @@ function useSendTransactionExtended(settings) {
|
|
|
241
243
|
};
|
|
242
244
|
}
|
|
243
245
|
|
|
244
|
-
|
|
246
|
+
const queryConfig = {
|
|
247
|
+
metadataQueryConfig: {
|
|
248
|
+
staleTime: Infinity,
|
|
249
|
+
},
|
|
250
|
+
sensitiveDataQueryConfig: {
|
|
251
|
+
staleTime: 60000,
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const EthTokenData = {
|
|
256
|
+
symbol: "ETH",
|
|
257
|
+
decimals: 18,
|
|
258
|
+
name: "Ethereum",
|
|
259
|
+
};
|
|
260
|
+
async function fetchDecimals(token, queryClient, wagmiConfig) {
|
|
261
|
+
if (token === zeroAddress)
|
|
262
|
+
return EthTokenData.decimals;
|
|
263
|
+
const decimals = await queryClient.fetchQuery({
|
|
264
|
+
...readContractQueryOptions(wagmiConfig, {
|
|
265
|
+
address: token,
|
|
266
|
+
abi: erc20Abi,
|
|
267
|
+
functionName: "decimals",
|
|
268
|
+
}),
|
|
269
|
+
...queryConfig.metadataQueryConfig,
|
|
270
|
+
});
|
|
271
|
+
return decimals;
|
|
272
|
+
}
|
|
273
|
+
async function fetchSymbol(token, queryClient, wagmiConfig) {
|
|
274
|
+
if (token === zeroAddress)
|
|
275
|
+
return EthTokenData.symbol;
|
|
276
|
+
const symbol = await queryClient.fetchQuery({
|
|
277
|
+
...readContractQueryOptions(wagmiConfig, {
|
|
278
|
+
address: token,
|
|
279
|
+
abi: erc20Abi,
|
|
280
|
+
functionName: "symbol",
|
|
281
|
+
}),
|
|
282
|
+
...queryConfig.metadataQueryConfig,
|
|
283
|
+
});
|
|
284
|
+
return symbol;
|
|
285
|
+
}
|
|
286
|
+
async function fetchName(token, queryClient, wagmiConfig) {
|
|
287
|
+
if (token === zeroAddress)
|
|
288
|
+
return EthTokenData.name;
|
|
289
|
+
const name = await queryClient.fetchQuery({
|
|
290
|
+
...readContractQueryOptions(wagmiConfig, {
|
|
291
|
+
address: token,
|
|
292
|
+
abi: erc20Abi,
|
|
293
|
+
functionName: "name",
|
|
294
|
+
}),
|
|
295
|
+
...queryConfig.metadataQueryConfig,
|
|
296
|
+
});
|
|
297
|
+
return name;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Fetches the token metadata (symbol, decimals) for the given token address.
|
|
301
|
+
* Internally calls:
|
|
302
|
+
* - `fetchSymbol(token)` to retrieve the token symbol,
|
|
303
|
+
* - `fetchDecimals(token)` to retrieve the token decimals
|
|
304
|
+
* - `fetchName(token)` to retrieve the token name
|
|
305
|
+
*
|
|
306
|
+
* @param token - The address of the token.
|
|
307
|
+
* @returns A `Token` object containing the symbol, decimals.
|
|
308
|
+
* @throws Will throw an error if symbol or decimals cannot be fetched.
|
|
309
|
+
*/
|
|
310
|
+
async function fetchToken(token, queryClient, wagmiConfig) {
|
|
311
|
+
const [symbol, decimals, name] = await Promise.all([
|
|
312
|
+
fetchSymbol(token, queryClient, wagmiConfig),
|
|
313
|
+
fetchDecimals(token, queryClient, wagmiConfig),
|
|
314
|
+
fetchName(token, queryClient, wagmiConfig),
|
|
315
|
+
]);
|
|
316
|
+
if (!symbol || !decimals) {
|
|
317
|
+
throw new Error("Failed to fetch token data");
|
|
318
|
+
}
|
|
319
|
+
return {
|
|
320
|
+
symbol,
|
|
321
|
+
decimals,
|
|
322
|
+
name,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const fetchAllowance = async (asset, spender, userAddress, queryClient, config) => {
|
|
327
|
+
const [tokenData, allowance] = await Promise.all([
|
|
328
|
+
fetchToken(asset, queryClient, config),
|
|
329
|
+
readContract(config, {
|
|
330
|
+
address: asset,
|
|
331
|
+
abi: erc20Abi,
|
|
332
|
+
functionName: "allowance",
|
|
333
|
+
args: [userAddress, spender],
|
|
334
|
+
}),
|
|
335
|
+
]);
|
|
336
|
+
if (!tokenData || allowance == null) {
|
|
337
|
+
throw new Error("Failed to fetch token data or allowance");
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
bigIntValue: allowance,
|
|
341
|
+
decimals: tokenData.decimals,
|
|
342
|
+
symbol: tokenData.symbol,
|
|
343
|
+
};
|
|
344
|
+
};
|
|
345
|
+
const HookFetchAssetAllowanceQK = (asset, spender, userAddress, config, queryClient) => [
|
|
346
|
+
"hookFetchAllowance",
|
|
347
|
+
asset,
|
|
348
|
+
spender,
|
|
349
|
+
userAddress,
|
|
350
|
+
config,
|
|
351
|
+
queryClient,
|
|
352
|
+
];
|
|
353
|
+
/**
|
|
354
|
+
* Custom hook for fetching asset allowance.
|
|
355
|
+
*
|
|
356
|
+
* @param {Address} asset - The address of the ERC20 token contract.
|
|
357
|
+
* @param {Address} spender - The address of the spender to check allowance for.
|
|
358
|
+
*/
|
|
359
|
+
const useFetchAssetAllowance = ({ asset, spender, }) => {
|
|
360
|
+
const config = useConfig();
|
|
361
|
+
const queryClient = useQueryClient();
|
|
362
|
+
const { address: userAddress } = useAccount();
|
|
363
|
+
const { data, ...rest } = useQuery({
|
|
364
|
+
queryKey: HookFetchAssetAllowanceQK(asset, spender, userAddress, config, queryClient),
|
|
365
|
+
queryFn: () => fetchAllowance(asset, spender, userAddress, queryClient, config),
|
|
366
|
+
enabled: !!asset && !!spender && !!userAddress,
|
|
367
|
+
...queryConfig.sensitiveDataQueryConfig,
|
|
368
|
+
});
|
|
369
|
+
return {
|
|
370
|
+
...rest,
|
|
371
|
+
data,
|
|
372
|
+
queryKey: HookFetchAssetAllowanceQK(asset, spender, userAddress, config, queryClient),
|
|
373
|
+
};
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Helper function to determine human readable state of approve.
|
|
378
|
+
*
|
|
379
|
+
* @param {boolean} isApproved - Indicates if the approval is already done.
|
|
380
|
+
* @param {boolean} justApproved - Indicates if the user has just approved.
|
|
381
|
+
* @return {string} - The appropriate button text.
|
|
382
|
+
*/
|
|
383
|
+
function getApproveState(isApproved, justApproved) {
|
|
384
|
+
if (isApproved) {
|
|
385
|
+
return justApproved ? "Approve Confirmed" : "Approved";
|
|
386
|
+
}
|
|
387
|
+
return "Approve";
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Custom hook for approving ERC20 token transfers.
|
|
391
|
+
*
|
|
392
|
+
* This hook provides functionality for approving ERC20 token transfers, checking the current allowance, and handling the approval transaction using Wagmi.
|
|
393
|
+
*
|
|
394
|
+
* @param {Address} tokenAddress - The address of the ERC20 token contract.
|
|
395
|
+
* @param {Address} spenderAddress - The address of the spender to approve the transfer to.
|
|
396
|
+
* @param {bigint} [amount=BigInt(0)] - The amount of tokens to approve for transfer. Defaults to 0.
|
|
397
|
+
* @returns {Object} Object containing the following properties:
|
|
398
|
+
* - {boolean} isApproved - Indicates whether the spender is already approved to transfer the specified amount of tokens.
|
|
399
|
+
* - {boolean} isApproving - Indicates whether an approval transaction is currently pending.
|
|
400
|
+
* - {Function} approveAsync - Function to trigger the approval transaction.
|
|
401
|
+
*/
|
|
402
|
+
const useERC20Approve = (tokenAddress, spenderAddress, amount) => {
|
|
403
|
+
const [isApproved, setIsApproved] = useState(false);
|
|
404
|
+
const [justApproved, setJustApproved] = useState(false);
|
|
405
|
+
const { data: allowance, queryKey } = useFetchAssetAllowance({
|
|
406
|
+
asset: tokenAddress,
|
|
407
|
+
spender: spenderAddress,
|
|
408
|
+
});
|
|
409
|
+
const { writeContractAsync: approveTokenAsync, isPending } = useContractWriteExtended({
|
|
410
|
+
queriesToInvalidate: [queryKey],
|
|
411
|
+
});
|
|
412
|
+
useEffect(() => {
|
|
413
|
+
if (amount == null) {
|
|
414
|
+
setIsApproved(false);
|
|
415
|
+
}
|
|
416
|
+
else if (allowance && allowance.bigIntValue >= amount) {
|
|
417
|
+
setIsApproved(true);
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
setIsApproved(false);
|
|
421
|
+
}
|
|
422
|
+
}, [allowance, amount]);
|
|
423
|
+
const approveAsync = async () => {
|
|
424
|
+
const amountToApprove = amount;
|
|
425
|
+
if (!spenderAddress) {
|
|
426
|
+
throw new Error("spenderAddress is undefined!");
|
|
427
|
+
}
|
|
428
|
+
if (!tokenAddress) {
|
|
429
|
+
throw new Error("tokenAddress is undefined!");
|
|
430
|
+
}
|
|
431
|
+
if (amountToApprove == null) {
|
|
432
|
+
throw new Error("amountToApprove is undefined!");
|
|
433
|
+
}
|
|
434
|
+
try {
|
|
435
|
+
await approveTokenAsync({
|
|
436
|
+
address: tokenAddress,
|
|
437
|
+
abi: erc20Abi,
|
|
438
|
+
functionName: "approve",
|
|
439
|
+
args: [spenderAddress, amountToApprove],
|
|
440
|
+
}, {
|
|
441
|
+
onSuccess: () => {
|
|
442
|
+
setJustApproved(true);
|
|
443
|
+
},
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
catch (e) {
|
|
447
|
+
console.error("Error approving token:", e);
|
|
448
|
+
throw e;
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
return {
|
|
452
|
+
isApproved,
|
|
453
|
+
isApproving: isPending,
|
|
454
|
+
justApproved,
|
|
455
|
+
approveAsync,
|
|
456
|
+
};
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
export { getApproveState, getErrorMapping, getParsedError, resetErrorMapping, setErrorMapping, useContractWriteExtended, useERC20Approve, useSendTransactionExtended };
|
|
245
460
|
//# sourceMappingURL=index.esm.js.map
|