wagmi-extended 0.4.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.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":[],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.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":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare const queryConfig: {
2
+ metadataQueryConfig: {
3
+ staleTime: number;
4
+ };
5
+ sensitiveDataQueryConfig: {
6
+ staleTime: number;
7
+ };
8
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wagmi-extended",
3
- "version": "0.4.0",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "description": "A library providing extended hooks on top of Wagmi with additional features.",
6
6
  "main": "dist/index.cjs.js",
@@ -29,7 +29,8 @@
29
29
  "author": "Srdjan Rakic <bans.cowboy@gmail.com>",
30
30
  "license": "MIT",
31
31
  "scripts": {
32
- "build": "rollup -c --bundleConfigAsCjs",
32
+ "clean": "rimraf dist",
33
+ "build": "npm run clean && npm version minor && rollup -c --bundleConfigAsCjs",
33
34
  "prepublishOnly": "npm run build"
34
35
  },
35
36
  "peerDependencies": {
@@ -44,6 +45,7 @@
44
45
  "@rollup/plugin-typescript": "^12.1.2",
45
46
  "@types/node": "^22.14.0",
46
47
  "@types/react": "^19.1.0",
48
+ "rimraf": "^6.0.1",
47
49
  "rollup": "^4.39.0",
48
50
  "rollup-plugin-peer-deps-external": "^2.2.4",
49
51
  "typescript": "^5.0.0"
@@ -2,7 +2,7 @@ import { useWriteContract } from "wagmi";
2
2
  import {
3
3
  WriteExtendedAsyncParams,
4
4
  useHandleTransactionMutation,
5
- } from "./useHandleTransactionMutation";
5
+ } from "./useHandleTransactionMutation.js";
6
6
 
7
7
  /**
8
8
  * Custom hook for writing to a smart contract using Wagmi.
@@ -0,0 +1,104 @@
1
+ import { useState, useEffect } from "react";
2
+ import { Address, maxUint256, erc20Abi } from "viem";
3
+ import { useFetchAssetAllowance } from "./useFetchAssetAllowance.js";
4
+ import { useContractWriteExtended } from "./useContractWriteExtended.js";
5
+
6
+ const ALWAYS_APPROVE_MAX = false;
7
+
8
+ /**
9
+ * Helper function to determine human readable state of approve.
10
+ *
11
+ * @param {boolean} isApproved - Indicates if the approval is already done.
12
+ * @param {boolean} justApproved - Indicates if the user has just approved.
13
+ * @return {string} - The appropriate button text.
14
+ */
15
+
16
+ export function getApproveState(isApproved?: boolean, justApproved?: boolean) {
17
+ if (isApproved) {
18
+ return justApproved ? "Approve Confirmed" : "Approved";
19
+ }
20
+ return "Approve";
21
+ }
22
+
23
+ /**
24
+ * Custom hook for approving ERC20 token transfers.
25
+ *
26
+ * This hook provides functionality for approving ERC20 token transfers, checking the current allowance, and handling the approval transaction using Wagmi.
27
+ *
28
+ * @param {Address} tokenAddress - The address of the ERC20 token contract.
29
+ * @param {Address} spenderAddress - The address of the spender to approve the transfer to.
30
+ * @param {bigint} [amount=BigInt(0)] - The amount of tokens to approve for transfer. Defaults to 0.
31
+ * @returns {Object} Object containing the following properties:
32
+ * - {boolean} isApproved - Indicates whether the spender is already approved to transfer the specified amount of tokens.
33
+ * - {boolean} isApproving - Indicates whether an approval transaction is currently pending.
34
+ * - {Function} approveAsync - Function to trigger the approval transaction.
35
+ */
36
+
37
+ export const useERC20Approve = (
38
+ tokenAddress?: Address,
39
+ spenderAddress?: Address,
40
+ amount?: bigint
41
+ ) => {
42
+ const [isApproved, setIsApproved] = useState(false);
43
+ const [justApproved, setJustApproved] = useState(false);
44
+
45
+ const { data: allowance, queryKey } = useFetchAssetAllowance({
46
+ asset: tokenAddress,
47
+ spender: spenderAddress,
48
+ });
49
+
50
+ const { writeContractAsync: approveTokenAsync, isPending } =
51
+ useContractWriteExtended({
52
+ queriesToInvalidate: [queryKey],
53
+ });
54
+
55
+ useEffect(() => {
56
+ if (amount == null) {
57
+ setIsApproved(false);
58
+ } else if (allowance && allowance.bigIntValue >= amount) {
59
+ setIsApproved(true);
60
+ } else {
61
+ setIsApproved(false);
62
+ }
63
+ }, [allowance, amount]);
64
+
65
+ const approveAsync = async () => {
66
+ const amountToApprove = ALWAYS_APPROVE_MAX ? maxUint256 : amount;
67
+
68
+ if (!spenderAddress) {
69
+ throw new Error("spenderAddress is undefined!");
70
+ }
71
+ if (!tokenAddress) {
72
+ throw new Error("tokenAddress is undefined!");
73
+ }
74
+ if (amountToApprove == null) {
75
+ throw new Error("amountToApprove is undefined!");
76
+ }
77
+
78
+ try {
79
+ await approveTokenAsync(
80
+ {
81
+ address: tokenAddress,
82
+ abi: erc20Abi,
83
+ functionName: "approve",
84
+ args: [spenderAddress, amountToApprove],
85
+ },
86
+ {
87
+ onSuccess: () => {
88
+ setJustApproved(true);
89
+ },
90
+ }
91
+ );
92
+ } catch (e: any) {
93
+ console.error("Error approving token:", e);
94
+ throw e;
95
+ }
96
+ };
97
+
98
+ return {
99
+ isApproved,
100
+ isApproving: isPending,
101
+ justApproved,
102
+ approveAsync,
103
+ };
104
+ };
@@ -0,0 +1,94 @@
1
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
2
+ import { Address, erc20Abi } from "viem";
3
+ import { readContract } from "viem/actions";
4
+ import { useAccount, useConfig } from "wagmi";
5
+ import { fetchToken } from "./useToken.js";
6
+ import { queryConfig } from "../query-config/index.js";
7
+
8
+ export const fetchAllowance = async (
9
+ asset: Address,
10
+ spender: Address,
11
+ userAddress: Address,
12
+ queryClient: any,
13
+ config: any
14
+ ) => {
15
+ const [tokenData, allowance] = await Promise.all([
16
+ fetchToken(asset, queryClient, config),
17
+ readContract(config, {
18
+ address: asset,
19
+ abi: erc20Abi,
20
+ functionName: "allowance",
21
+ args: [userAddress, spender],
22
+ }),
23
+ ]);
24
+
25
+ if (!tokenData || allowance == null) {
26
+ throw new Error("Failed to fetch token data or allowance");
27
+ }
28
+
29
+ return {
30
+ bigIntValue: allowance,
31
+ decimals: tokenData.decimals,
32
+ symbol: tokenData.symbol,
33
+ };
34
+ };
35
+
36
+ const HookFetchAssetAllowanceQK = (
37
+ asset: Address,
38
+ spender: Address,
39
+ userAddress: Address,
40
+ config: any,
41
+ queryClient: any
42
+ ) =>
43
+ [
44
+ "hookFetchAllowance",
45
+ asset,
46
+ spender,
47
+ userAddress,
48
+ config,
49
+ queryClient,
50
+ ] as const;
51
+
52
+ /**
53
+ * Custom hook for fetching asset allowance.
54
+ *
55
+ * @param {Address} asset - The address of the ERC20 token contract.
56
+ * @param {Address} spender - The address of the spender to check allowance for.
57
+ */
58
+ export const useFetchAssetAllowance = ({
59
+ asset,
60
+ spender,
61
+ }: {
62
+ asset?: Address;
63
+ spender?: Address;
64
+ }) => {
65
+ const config = useConfig();
66
+ const queryClient = useQueryClient();
67
+ const { address: userAddress } = useAccount();
68
+
69
+ const { data, ...rest } = useQuery({
70
+ queryKey: HookFetchAssetAllowanceQK(
71
+ asset!,
72
+ spender!,
73
+ userAddress!,
74
+ config,
75
+ queryClient
76
+ ),
77
+ queryFn: () =>
78
+ fetchAllowance(asset!, spender!, userAddress!, queryClient, config),
79
+ enabled: !!asset && !!spender && !!userAddress,
80
+ ...queryConfig.sensitiveDataQueryConfig,
81
+ });
82
+
83
+ return {
84
+ ...rest,
85
+ data,
86
+ queryKey: HookFetchAssetAllowanceQK(
87
+ asset!,
88
+ spender!,
89
+ userAddress!,
90
+ config,
91
+ queryClient
92
+ ),
93
+ };
94
+ };
@@ -1,10 +1,10 @@
1
1
  import { waitForTransactionReceipt } from "wagmi/actions";
2
- import { useInvalidateQueries } from "./useInvalidateQueries";
3
2
  import { useConfig } from "wagmi";
4
3
  import { QueryKey } from "@tanstack/query-core";
5
4
  import { Address } from "viem";
6
5
  import { useState } from "react";
7
- import { getParsedError } from "../utils/errorParser";
6
+ import { getParsedError } from "../utils/errorParser.js";
7
+ import { useInvalidateQueries } from "./useInvalidateQueries.js";
8
8
 
9
9
  export type WriteExtendedAsyncParams = {
10
10
  onSuccess?: (txHash: Address) => void;
@@ -1,7 +1,7 @@
1
1
  import { Hash } from "viem";
2
2
  import { useSendTransaction } from "wagmi";
3
3
  import { QueryKey } from "@tanstack/query-core";
4
- import { useHandleTransactionMutation } from "./useHandleTransactionMutation";
4
+ import { useHandleTransactionMutation } from "./useHandleTransactionMutation.js";
5
5
 
6
6
  export type SeamlessSendAsyncParams = {
7
7
  onSuccess?: (txHash: Hash) => void;
@@ -0,0 +1,122 @@
1
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
2
+ import { readContractQueryOptions } from "wagmi/query";
3
+ import { Address, zeroAddress, erc20Abi } from "viem";
4
+ import { queryConfig } from "../query-config/index.js";
5
+ import { useConfig } from "wagmi";
6
+
7
+ export interface Token {
8
+ symbol: string;
9
+ decimals: number;
10
+ name: string;
11
+ }
12
+
13
+ export const EthTokenData: Token = {
14
+ symbol: "ETH",
15
+ decimals: 18,
16
+ name: "Ethereum",
17
+ };
18
+
19
+ export async function fetchDecimals(
20
+ token: Address,
21
+ queryClient: any,
22
+ wagmiConfig: any
23
+ ): Promise<number | undefined> {
24
+ if (token === zeroAddress) return EthTokenData.decimals;
25
+
26
+ const decimals = await queryClient.fetchQuery({
27
+ ...readContractQueryOptions(wagmiConfig, {
28
+ address: token,
29
+ abi: erc20Abi,
30
+ functionName: "decimals",
31
+ }),
32
+ ...queryConfig.metadataQueryConfig,
33
+ });
34
+
35
+ return decimals;
36
+ }
37
+
38
+ export async function fetchSymbol(
39
+ token: Address,
40
+ queryClient: any,
41
+ wagmiConfig: any
42
+ ): Promise<string> {
43
+ if (token === zeroAddress) return EthTokenData.symbol;
44
+
45
+ const symbol = await queryClient.fetchQuery({
46
+ ...readContractQueryOptions(wagmiConfig, {
47
+ address: token,
48
+ abi: erc20Abi,
49
+ functionName: "symbol",
50
+ }),
51
+ ...queryConfig.metadataQueryConfig,
52
+ });
53
+
54
+ return symbol;
55
+ }
56
+
57
+ export async function fetchName(
58
+ token: Address,
59
+ queryClient: any,
60
+ wagmiConfig: any
61
+ ): Promise<string> {
62
+ if (token === zeroAddress) return EthTokenData.name;
63
+
64
+ const name = await queryClient.fetchQuery({
65
+ ...readContractQueryOptions(wagmiConfig, {
66
+ address: token,
67
+ abi: erc20Abi,
68
+ functionName: "name",
69
+ }),
70
+ ...queryConfig.metadataQueryConfig,
71
+ });
72
+
73
+ return name;
74
+ }
75
+
76
+ /**
77
+ * Fetches the token metadata (symbol, decimals) for the given token address.
78
+ * Internally calls:
79
+ * - `fetchSymbol(token)` to retrieve the token symbol,
80
+ * - `fetchDecimals(token)` to retrieve the token decimals
81
+ * - `fetchName(token)` to retrieve the token name
82
+ *
83
+ * @param token - The address of the token.
84
+ * @returns A `Token` object containing the symbol, decimals.
85
+ * @throws Will throw an error if symbol or decimals cannot be fetched.
86
+ */
87
+ export async function fetchToken(
88
+ token: Address,
89
+ queryClient: any,
90
+ wagmiConfig: any
91
+ ): Promise<Token> {
92
+ const [symbol, decimals, name] = await Promise.all([
93
+ fetchSymbol(token, queryClient, wagmiConfig),
94
+ fetchDecimals(token, queryClient, wagmiConfig),
95
+ fetchName(token, queryClient, wagmiConfig),
96
+ ]);
97
+ if (!symbol || !decimals) {
98
+ throw new Error("Failed to fetch token data");
99
+ }
100
+
101
+ return {
102
+ symbol,
103
+ decimals,
104
+ name,
105
+ };
106
+ }
107
+
108
+ export const useToken = (asset?: Address) => {
109
+ const queryClient = useQueryClient();
110
+ const config = useConfig();
111
+
112
+ const { data, ...rest } = useQuery({
113
+ queryKey: ["useTokenWagmiExtended", asset],
114
+ queryFn: () => fetchToken(asset!, queryClient, config),
115
+ enabled: Boolean(asset),
116
+ });
117
+
118
+ return {
119
+ ...rest,
120
+ data,
121
+ };
122
+ };
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
- export * from "./hooks/useContractWriteExtended";
2
- export * from "./hooks/useSendTransactionExtended";
3
- export * from "./utils/errorParser";
1
+ export * from "./hooks/useContractWriteExtended.js";
2
+ export * from "./hooks/useSendTransactionExtended.js";
3
+ export * from "./hooks/useERC20Approve.js";
4
+ export * from "./utils/errorParser.js";
@@ -0,0 +1,8 @@
1
+ export const queryConfig = {
2
+ metadataQueryConfig: {
3
+ staleTime: Infinity,
4
+ },
5
+ sensitiveDataQueryConfig: {
6
+ staleTime: 60_000,
7
+ },
8
+ };
package/tsconfig.json CHANGED
@@ -1,7 +1,15 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ES2019",
4
- "module": "esnext",
4
+ "module": "nodenext",
5
+ "baseUrl": ".", // important when using paths
6
+ "paths": {
7
+ "wagmi/query": ["node_modules/wagmi/query"],
8
+ "@tanstack/react-query/build/legacy/useQuery": [
9
+ "node_modules/@tanstack/react-query/build/legacy/useQuery"
10
+ ],
11
+ "viem": ["node_modules/viem"]
12
+ },
5
13
  "declaration": true,
6
14
  "outDir": "dist",
7
15
  "strict": true,