wagmi-extended 2.1.1 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,54 @@
1
+ import type { Address } from "viem";
2
+ import type { QueryClient } from "@tanstack/react-query";
3
+ import type { Config } from "wagmi";
4
+ /** Reusable React Query key helper for deployment block lookups. */
5
+ export declare const deploymentBlockKey: (chainId: number | undefined, address: Address | undefined, floor: bigint) => readonly ["deploymentBlock", number | undefined, string | undefined, bigint];
6
+ /**
7
+ * Builds React Query options for caching the deployment block "forever".
8
+ *
9
+ * Use with `queryClient.fetchQuery(...)`.
10
+ *
11
+ * @param address - Contract address to probe.
12
+ * @param floor - Optional lower bound (inclusive) to speed up search. Defaults to `0n`.
13
+ * @param wagmiConfig - Wagmi `Config` (optional; resolved via `ensureClientAndConfig` if omitted).
14
+ *
15
+ * @returns A fully-configured query options object (key + fn + metadata).
16
+ */
17
+ export declare function getDeploymentBlockQueryOptionsX(address: Address, floor?: bigint, wagmiConfig?: Config): {
18
+ readonly staleTime: number;
19
+ readonly meta: {
20
+ readonly queryType: import("../../query-config/index.js").QueryType.MetaDataQuery;
21
+ };
22
+ readonly queryKey: readonly ["deploymentBlock", number | undefined, string | undefined, bigint];
23
+ readonly queryFn: () => Promise<bigint>;
24
+ };
25
+ /**
26
+ * Fetches (and caches) the first block where contract bytecode exists at `address`.
27
+ *
28
+ * Uses your shared `QueryClient` and Wagmi `Config` like other `fetch*X` helpers.
29
+ * Internally, this runs an **exponential descent** to find a safe lower bound,
30
+ * followed by an **optimal binary search** to pinpoint the exact deployment block.
31
+ *
32
+ * #### Caching
33
+ * - Query key: `["deploymentBlock", chainId, address.toLowerCase(), floor]`
34
+ * - For long-lived results, we apply `queryConfig.metaDataQuery` (tweak as needed).
35
+ *
36
+ * #### Performance
37
+ * - **O(log N)** `eth_getCode` calls, where `N` is the gap between the latest
38
+ * block and the deployment block—optimal among comparison-based strategies.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * const block = await fetchDeploymentBlockX("0xContract...", 0n, queryClient, wagmiConfig);
43
+ * ```
44
+ *
45
+ * @param address - Contract address to probe.
46
+ * @param floor - Optional lower bound (inclusive) to speed up search. Defaults to `0n`.
47
+ * @param queryClient - Optional TanStack `QueryClient`. If omitted, resolved by `ensureClientAndConfig`.
48
+ * @param wagmiConfig - Optional Wagmi `Config`. If omitted, resolved by `ensureClientAndConfig`.
49
+ *
50
+ * @returns The earliest block number (bigint) where bytecode exists.
51
+ *
52
+ * @throws If the public client is missing or if no code is present at the latest block.
53
+ */
54
+ export declare function fetchDeploymentBlockX(address: Address, floor?: bigint, queryClient?: QueryClient, wagmiConfig?: Config): Promise<bigint>;
@@ -1,4 +1,5 @@
1
1
  import { Address } from "viem";
2
+ export declare const HookFetchERC20DataQK: (address?: Address, userAddress?: Address, spender?: Address) => readonly ["HookFetchERC20Data", `0x${string}` | undefined, `0x${string}` | undefined, `0x${string}` | undefined];
2
3
  /**
3
4
  * Hook to fetch ERC-20 summary data for a given token and optional user/spender context.
4
5
  *
@@ -1,4 +1,5 @@
1
1
  import { Address } from "viem";
2
+ export declare const HookFetchAssetAllowanceQK: (asset?: Address, spender?: Address, userAddress?: Address) => readonly ["HookFetchAllowance", `0x${string}` | undefined, `0x${string}` | undefined, `0x${string}` | undefined];
2
3
  /**
3
4
  * Custom hook for fetching asset allowance.
4
5
  *
@@ -1,4 +1,5 @@
1
1
  import { Address } from "viem";
2
+ export declare const HookFetchERC4626DataQK: (vault?: Address, userAddress?: Address, spender?: Address) => readonly ["HookFetchERC4626Data", `0x${string}` | undefined, `0x${string}` | undefined, `0x${string}` | undefined];
2
3
  /**
3
4
  * Hook to fetch ERC-4626 vault summary data for a given vault and user/spender.
4
5
  *
package/dist/index.cjs.js CHANGED
@@ -87,16 +87,18 @@ const getErrorMapping = () => currentErrorMapping;
87
87
  * console.log(message); // Outputs a custom error message or a default error message.
88
88
  */
89
89
  const getParsedErrorX = (error) => {
90
- var _a, _b, _c, _d;
91
90
  const defaultMessage = "An unknown error occurred. Please contact support.";
92
91
  let message = defaultMessage;
93
92
  let errorKey = "";
94
- const revertedError = (error === null || error === void 0 ? void 0 : error.walk)
93
+ const revertedError = error?.walk
95
94
  ? error.walk((err) => err instanceof viem.ContractFunctionRevertedError)
96
95
  : null;
97
96
  if (revertedError instanceof viem.ContractFunctionRevertedError) {
98
97
  errorKey =
99
- (_d = (_c = (_b = (_a = revertedError.data) === null || _a === void 0 ? void 0 : _a.errorName) !== null && _b !== void 0 ? _b : revertedError.signature) !== null && _c !== void 0 ? _c : revertedError.reason) !== null && _d !== void 0 ? _d : "";
98
+ revertedError.data?.errorName ??
99
+ revertedError.signature ??
100
+ revertedError.reason ??
101
+ "";
100
102
  if (currentErrorMapping[errorKey])
101
103
  return currentErrorMapping[errorKey];
102
104
  }
@@ -120,11 +122,10 @@ function useHandleTransactionMutationX({ settings, }) {
120
122
  setErrorMessage(undefined);
121
123
  };
122
124
  const onSettled = async (txHash, error, args) => {
123
- var _a, _b, _c;
124
125
  try {
125
126
  if (error)
126
127
  throw error;
127
- if (!(settings === null || settings === void 0 ? void 0 : settings.disableWaitingForReceipt)) {
128
+ if (!settings?.disableWaitingForReceipt) {
128
129
  // 1. wait for transaction receipt
129
130
  const txReceipt = await actions.waitForTransactionReceipt(wagmiConfig, {
130
131
  hash: txHash,
@@ -148,10 +149,10 @@ function useHandleTransactionMutationX({ settings, }) {
148
149
  await invalidateMany(queriesToInvalidate);
149
150
  }
150
151
  // 4. call onSuccess callback
151
- (_a = settings === null || settings === void 0 ? void 0 : settings.onSuccess) === null || _a === void 0 ? void 0 : _a.call(settings, txHash);
152
- if (settings === null || settings === void 0 ? void 0 : settings.onSuccessAsync)
152
+ settings?.onSuccess?.(txHash);
153
+ if (settings?.onSuccessAsync)
153
154
  await settings.onSuccessAsync(txHash);
154
- if (!(settings === null || settings === void 0 ? void 0 : settings.disableLogging)) {
155
+ if (!settings?.disableLogging) {
155
156
  // 5. log result
156
157
  // eslint-disable-next-line no-console
157
158
  console.info("Operation successful:", txHash); // todo: add logging service
@@ -161,7 +162,7 @@ function useHandleTransactionMutationX({ settings, }) {
161
162
  }
162
163
  catch (error) {
163
164
  const parsedError = getParsedErrorX(error);
164
- if (!(settings === null || settings === void 0 ? void 0 : settings.disableLogging)) {
165
+ if (!settings?.disableLogging) {
165
166
  // 1. log error
166
167
  console.error(`ContractWriteExtended Operation failed with error(parsed): ${parsedError}`, { error }, { args });
167
168
  console.error({ error });
@@ -169,15 +170,15 @@ function useHandleTransactionMutationX({ settings, }) {
169
170
  // 2. set error message
170
171
  setErrorMessage(parsedError);
171
172
  // 3. call callback
172
- (_b = settings === null || settings === void 0 ? void 0 : settings.onError) === null || _b === void 0 ? void 0 : _b.call(settings, error);
173
- if (settings === null || settings === void 0 ? void 0 : settings.onErrorAsync)
173
+ settings?.onError?.(error);
174
+ if (settings?.onErrorAsync)
174
175
  await settings.onErrorAsync(error);
175
176
  }
176
177
  finally {
177
178
  setIsPending(false);
178
179
  // 1. call callback
179
- (_c = settings === null || settings === void 0 ? void 0 : settings.onSettled) === null || _c === void 0 ? void 0 : _c.call(settings);
180
- if (settings === null || settings === void 0 ? void 0 : settings.onSettledAsync)
180
+ settings?.onSettled?.();
181
+ if (settings?.onSettledAsync)
181
182
  await settings.onSettledAsync();
182
183
  }
183
184
  return undefined;
@@ -227,10 +228,10 @@ function useContractWriteX(settings) {
227
228
  // 1) optional dry-run
228
229
  const { chain, ...others } = params;
229
230
  if (!disableSimulation) {
230
- await (publicClient === null || publicClient === void 0 ? void 0 : publicClient.simulateContract({
231
+ await publicClient?.simulateContract({
231
232
  ...others,
232
233
  ...(chain != null ? { chain } : {}),
233
- }));
234
+ });
234
235
  }
235
236
  wagmiWrite.writeContract(params);
236
237
  }
@@ -292,21 +293,20 @@ function useSendTransactionX(settings) {
292
293
  * @returns {Promise<void>}
293
294
  */
294
295
  async function sendTransactionX(params, simulationParams) {
295
- var _a;
296
296
  onMutate();
297
297
  try {
298
298
  if (params.to && simulationParams) {
299
299
  //simulate!
300
- await (publicClient === null || publicClient === void 0 ? void 0 : publicClient.simulateContract({
300
+ await publicClient?.simulateContract({
301
301
  address: params.to,
302
302
  abi: simulationParams.abi,
303
303
  functionName: simulationParams.functionName,
304
- args: (_a = simulationParams.args) !== null && _a !== void 0 ? _a : [],
304
+ args: simulationParams.args ?? [],
305
305
  account: params.account,
306
306
  ...(simulationParams.chain != null
307
307
  ? { chain: simulationParams.chain }
308
308
  : {}),
309
- }));
309
+ });
310
310
  }
311
311
  // actual send!
312
312
  await sendTransaction(params);
@@ -324,19 +324,36 @@ function useSendTransactionX(settings) {
324
324
  };
325
325
  }
326
326
 
327
+ exports.QueryType = void 0;
328
+ (function (QueryType) {
329
+ QueryType["MetaDataQuery"] = "metaDataQuery";
330
+ QueryType["SemiSensitiveQuery"] = "semiSensitiveQuery";
331
+ QueryType["LowSensitiveQuery"] = "lowSensitiveQuery";
332
+ QueryType["ExpensiveQuery"] = "expensiveQuery";
333
+ QueryType["PriceQuery"] = "priceQuery";
334
+ })(exports.QueryType || (exports.QueryType = {}));
327
335
  const queryConfig = {
328
336
  metaDataQuery: {
329
337
  staleTime: Number.POSITIVE_INFINITY,
330
- meta: { category: "metadata" },
338
+ meta: { queryType: exports.QueryType.MetaDataQuery },
331
339
  },
332
340
  lowSensitiveQuery: {
333
341
  staleTime: 60000,
334
- meta: { category: "lowSensitive" },
342
+ meta: { queryType: exports.QueryType.SemiSensitiveQuery },
335
343
  },
336
344
  semiSensitiveQuery: {
337
345
  staleTime: 180000,
338
- meta: { category: "semiSensitive" },
339
- }};
346
+ meta: { queryType: exports.QueryType.LowSensitiveQuery },
347
+ },
348
+ priceQuery: {
349
+ staleTime: 30 * 60 * 1000,
350
+ meta: { queryType: exports.QueryType.PriceQuery },
351
+ },
352
+ expensiveQuery: {
353
+ staleTime: 60 * 60 * 1000,
354
+ meta: { queryType: exports.QueryType.ExpensiveQuery },
355
+ },
356
+ };
340
357
 
341
358
  // You can adjust the type for wagmiConfig to match your needs.
342
359
  let defaultQueryClient = null;
@@ -838,11 +855,150 @@ async function fetchERC4626DataX(vault, user, spender, queryClient, wagmiConfig)
838
855
  };
839
856
  }
840
857
 
858
+ /** Reusable React Query key helper for deployment block lookups. */
859
+ const deploymentBlockKey = (chainId, address, floor) => ["deploymentBlock", chainId, address?.toLowerCase(), floor];
860
+ /**
861
+ * Internal helper: checks if there is bytecode at `address` on `blockNumber`.
862
+ */
863
+ async function hasCodeAtX(address, blockNumber, wagmiConfig) {
864
+ const client = actions.getPublicClient(wagmiConfig);
865
+ if (!client)
866
+ throw new Error("Public client is missing");
867
+ const code = await client.getCode({ address, blockNumber });
868
+ return !!code && code !== "0x";
869
+ }
870
+ /**
871
+ * Internal helper: finds the earliest block where code exists at `address`,
872
+ * using exponential descent to find a lower bound and then binary search.
873
+ *
874
+ * @param address - Contract address to probe.
875
+ * @param floor - Optional lower bound (inclusive) to start from. If you know
876
+ * the contract cannot exist below this block, pass it to
877
+ * speed up the search. Defaults to `0n`.
878
+ * @returns The first block number (bigint) where code is present.
879
+ * @throws If no code exists at the latest block (i.e., contract not deployed).
880
+ */
881
+ async function findDeploymentBlockRpcX(address, wagmiConfig, floor = 0n) {
882
+ const client = actions.getPublicClient(wagmiConfig);
883
+ if (!client)
884
+ throw new Error("Public client is missing");
885
+ const latest = await client.getBlockNumber();
886
+ if (!(await hasCodeAtX(address, latest, wagmiConfig))) {
887
+ const chainId = client.chain?.id ?? 0;
888
+ throw new Error(`No code for ${address} at latest block ${latest} on chain ${chainId}.`);
889
+ }
890
+ // If caller-supplied floor already has code, it *is* the first code block.
891
+ if (floor > 0n && (await hasCodeAtX(address, floor, wagmiConfig)))
892
+ return floor;
893
+ // Exponential descent to find a "no code" lower bound fast.
894
+ let lo = floor; // known (or assumed) no code
895
+ let hi = latest; // known has code
896
+ let step = 1n;
897
+ while (hi - step > lo) {
898
+ const probe = hi - step;
899
+ if (await hasCodeAtX(address, probe, wagmiConfig)) {
900
+ hi = probe; // still has code -> move upper bound down
901
+ step <<= 1n; // double the step
902
+ }
903
+ else {
904
+ lo = probe; // found a no-code block
905
+ break;
906
+ }
907
+ }
908
+ // Binary search to the first block with code in (lo, hi]
909
+ while (lo + 1n < hi) {
910
+ const mid = lo + (hi - lo) / 2n;
911
+ if (await hasCodeAtX(address, mid, wagmiConfig))
912
+ hi = mid;
913
+ else
914
+ lo = mid;
915
+ }
916
+ return hi;
917
+ }
918
+ /**
919
+ * Builds React Query options for caching the deployment block "forever".
920
+ *
921
+ * Use with `queryClient.fetchQuery(...)`.
922
+ *
923
+ * @param address - Contract address to probe.
924
+ * @param floor - Optional lower bound (inclusive) to speed up search. Defaults to `0n`.
925
+ * @param wagmiConfig - Wagmi `Config` (optional; resolved via `ensureClientAndConfig` if omitted).
926
+ *
927
+ * @returns A fully-configured query options object (key + fn + metadata).
928
+ */
929
+ function getDeploymentBlockQueryOptionsX(address, floor = 0n, wagmiConfig) {
930
+ if (!address)
931
+ throw new Error("Address is required");
932
+ // Resolve config (caller may pass undefined; we'll normalize later in fetcher too)
933
+ // We only need chainId for the key; if wagmiConfig is missing here,
934
+ // we allow it since fetcher re-resolves. But key stability benefits from chainId.
935
+ const client = wagmiConfig ? actions.getPublicClient(wagmiConfig) : undefined;
936
+ const chainId = client?.chain?.id;
937
+ return {
938
+ queryKey: deploymentBlockKey(chainId, address, floor),
939
+ queryFn: async () => {
940
+ if (!wagmiConfig)
941
+ throw new Error("wagmiConfig is required at execution time");
942
+ return findDeploymentBlockRpcX(address, wagmiConfig, floor);
943
+ },
944
+ ...queryConfig.metaDataQuery,
945
+ };
946
+ }
947
+ /**
948
+ * Fetches (and caches) the first block where contract bytecode exists at `address`.
949
+ *
950
+ * Uses your shared `QueryClient` and Wagmi `Config` like other `fetch*X` helpers.
951
+ * Internally, this runs an **exponential descent** to find a safe lower bound,
952
+ * followed by an **optimal binary search** to pinpoint the exact deployment block.
953
+ *
954
+ * #### Caching
955
+ * - Query key: `["deploymentBlock", chainId, address.toLowerCase(), floor]`
956
+ * - For long-lived results, we apply `queryConfig.metaDataQuery` (tweak as needed).
957
+ *
958
+ * #### Performance
959
+ * - **O(log N)** `eth_getCode` calls, where `N` is the gap between the latest
960
+ * block and the deployment block—optimal among comparison-based strategies.
961
+ *
962
+ * @example
963
+ * ```ts
964
+ * const block = await fetchDeploymentBlockX("0xContract...", 0n, queryClient, wagmiConfig);
965
+ * ```
966
+ *
967
+ * @param address - Contract address to probe.
968
+ * @param floor - Optional lower bound (inclusive) to speed up search. Defaults to `0n`.
969
+ * @param queryClient - Optional TanStack `QueryClient`. If omitted, resolved by `ensureClientAndConfig`.
970
+ * @param wagmiConfig - Optional Wagmi `Config`. If omitted, resolved by `ensureClientAndConfig`.
971
+ *
972
+ * @returns The earliest block number (bigint) where bytecode exists.
973
+ *
974
+ * @throws If the public client is missing or if no code is present at the latest block.
975
+ */
976
+ async function fetchDeploymentBlockX(address, floor = 0n, queryClient, wagmiConfig) {
977
+ if (!address)
978
+ throw new Error("Address is required");
979
+ ({ queryClient, wagmiConfig } = ensureClientAndConfig(queryClient, wagmiConfig));
980
+ // Resolve chainId for a stable cache key
981
+ const client = actions.getPublicClient(wagmiConfig);
982
+ const chainId = client?.chain?.id;
983
+ if (!chainId)
984
+ throw new Error("Client chain ID is missing");
985
+ return queryClient.fetchQuery({
986
+ ...getDeploymentBlockQueryOptionsX(address, floor, wagmiConfig),
987
+ // Ensure the final key includes a concrete chainId
988
+ queryKey: deploymentBlockKey(chainId, address, floor),
989
+ // Reinstate metadata (in case your ensure/util merges)
990
+ ...queryConfig.metaDataQuery,
991
+ });
992
+ }
993
+
841
994
  exports.EthTokenData = EthTokenData;
995
+ exports.HookFetchAssetAllowanceQK = HookFetchAssetAllowanceQK;
842
996
  exports.HookFetchTokenQK = HookFetchTokenQK;
997
+ exports.deploymentBlockKey = deploymentBlockKey;
843
998
  exports.fetchAllowanceX = fetchAllowanceX;
844
999
  exports.fetchBalanceOfX = fetchBalanceOfX;
845
1000
  exports.fetchDecimalsX = fetchDecimalsX;
1001
+ exports.fetchDeploymentBlockX = fetchDeploymentBlockX;
846
1002
  exports.fetchERC20DataX = fetchERC20DataX;
847
1003
  exports.fetchERC4626AssetX = fetchERC4626AssetX;
848
1004
  exports.fetchERC4626DataX = fetchERC4626DataX;
@@ -856,8 +1012,10 @@ exports.fetchSymbolX = fetchSymbolX;
856
1012
  exports.fetchTokenX = fetchTokenX;
857
1013
  exports.fetchTotalSupplyX = fetchTotalSupplyX;
858
1014
  exports.getDefaults = getDefaults;
1015
+ exports.getDeploymentBlockQueryOptionsX = getDeploymentBlockQueryOptionsX;
859
1016
  exports.getErrorMapping = getErrorMapping;
860
1017
  exports.getParsedErrorX = getParsedErrorX;
1018
+ exports.queryConfig = queryConfig;
861
1019
  exports.resetErrorMapping = resetErrorMapping;
862
1020
  exports.setDefaults = setDefaults;
863
1021
  exports.setErrorMapping = setErrorMapping;