diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index 39cbd9d34..d9197274e 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -50,7 +50,7 @@ "@shazow/whatsabi": "^0.14.1", "@stripe/react-stripe-js": "^2.7.3", "@stripe/stripe-js": "^3.5.0", - "@tanstack/react-query": "^4.36.1", + "@tanstack/react-query": "5.55.4", "@tanstack/react-table": "^8.17.3", "@thirdweb-dev/sdk": "workspace:*", "@thirdweb-dev/service-utils": "workspace:*", @@ -93,7 +93,6 @@ "react-intersection-observer": "^9.10.3", "react-markdown": "^9.0.1", "react-otp-input": "^3.1.1", - "react-query-v5": "npm:@tanstack/react-query@5.55.4", "react-responsive-carousel": "^3.2.23", "react-table": "^7.8.0", "recharts": "^2.12.7", diff --git a/apps/dashboard/src/@3rdweb-sdk/react/hooks/query/useQueryWithNetwork.ts b/apps/dashboard/src/@3rdweb-sdk/react/hooks/query/useQueryWithNetwork.ts index aea7be5f8..4b6b24172 100644 --- a/apps/dashboard/src/@3rdweb-sdk/react/hooks/query/useQueryWithNetwork.ts +++ b/apps/dashboard/src/@3rdweb-sdk/react/hooks/query/useQueryWithNetwork.ts @@ -39,7 +39,11 @@ export function useQueryWithNetwork< networkKeys.chain(activeChainId) as readonly unknown[] ).concat(queryKey) as unknown as TQueryKey; - return useQuery(combinedQueryKey, queryFn, mergedOptions); + return useQuery({ + ...mergedOptions, + queryKey: combinedQueryKey, + queryFn, + }); } export function useMutationWithInvalidate< TData = unknown, @@ -71,19 +75,20 @@ export function useMutationWithInvalidate< (cacheKeysToInvalidate: TQueryKey[]) => { return Promise.all( cacheKeysToInvalidate.map((cacheKey) => { - return queryClient.invalidateQueries( - (networkKeys.chain(activeChainId) as readonly unknown[]).concat( - cacheKey, - ) as unknown[], - ); + return queryClient.invalidateQueries({ + queryKey: ( + networkKeys.chain(activeChainId) as readonly unknown[] + ).concat(cacheKey) as unknown[], + }); }), ); }, [queryClient, activeChainId], ); - return useMutation(mutationFn, { + return useMutation({ ...options, + mutationFn, onSuccess: (...args) => { if (options?.onSuccess) { options.onSuccess(...args, invalidate); diff --git a/apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts b/apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts index 0e00c5a19..4efc02419 100644 --- a/apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts +++ b/apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts @@ -254,15 +254,16 @@ export interface BillingCredit { interface UseAccountInput { refetchInterval?: | number + | false | (( - data: Account | undefined, query: Query< Account, - unknown, + Error, Account, readonly ["account", string, "me"] >, - ) => number | false); + ) => number | false | undefined) + | undefined; } export function useAccount({ refetchInterval }: UseAccountInput = {}) { @@ -286,7 +287,7 @@ export function useAccount({ refetchInterval }: UseAccountInput = {}) { return json.data as Account; }, enabled: !!user?.address && isLoggedIn, - refetchInterval: refetchInterval ?? false, + refetchInterval, }); } @@ -444,8 +445,8 @@ export function useUpdateAccount() { const { user } = useLoggedInUser(); const queryClient = useQueryClient(); - return useMutationWithInvalidate( - async (input: UpdateAccountInput) => { + return useMutation({ + mutationFn: async (input: UpdateAccountInput) => { invariant(user?.address, "walletAddress is required"); const res = await fetch(`${THIRDWEB_API_HOST}/v1/account`, { @@ -465,14 +466,13 @@ export function useUpdateAccount() { return json.data; }, - { - onSuccess: () => { - return queryClient.invalidateQueries( - accountKeys.me(user?.address as string), - ); - }, + + onSuccess: () => { + return queryClient.invalidateQueries({ + queryKey: accountKeys.me(user?.address as string), + }); }, - ); + }); } export function useUpdateAccountPlan(waitForWebhook?: boolean) { @@ -507,13 +507,15 @@ export function useUpdateAccountPlan(waitForWebhook?: boolean) { return json.data; }, { - onSuccess: () => { + onSuccess: async () => { // invalidate usage data as limits are different - queryClient.invalidateQueries(accountKeys.me(user?.address as string)); + await queryClient.invalidateQueries({ + queryKey: accountKeys.me(user?.address as string), + }); - return queryClient.invalidateQueries( - accountKeys.usage(user?.address as string), - ); + return queryClient.invalidateQueries({ + queryKey: accountKeys.usage(user?.address as string), + }); }, }, ); @@ -545,9 +547,9 @@ export function useUpdateNotifications() { }, { onSuccess: () => { - return queryClient.invalidateQueries( - accountKeys.me(user?.address as string), - ); + return queryClient.invalidateQueries({ + queryKey: accountKeys.me(user?.address as string), + }); }, }, ); @@ -608,16 +610,19 @@ export function useConfirmEmail() { return json.data; }, { - onSuccess: () => { + onSuccess: async () => { // invalidate related cache, since could be relinking account - queryClient.invalidateQueries(apiKeys.keys(user?.address as string)); - queryClient.invalidateQueries( - accountKeys.usage(user?.address as string), - ); - - return queryClient.invalidateQueries( - accountKeys.me(user?.address as string), - ); + return Promise.all([ + queryClient.invalidateQueries({ + queryKey: apiKeys.keys(user?.address as string), + }), + queryClient.invalidateQueries({ + queryKey: accountKeys.usage(user?.address as string), + }), + queryClient.invalidateQueries({ + queryKey: accountKeys.me(user?.address as string), + }), + ]); }, }, ); @@ -652,9 +657,9 @@ export function useResendEmailConfirmation() { }, { onSuccess: () => { - return queryClient.invalidateQueries( - accountKeys.me(user?.address as string), - ); + return queryClient.invalidateQueries({ + queryKey: accountKeys.me(user?.address as string), + }); }, }, ); @@ -688,9 +693,9 @@ export function useCreatePaymentMethod() { }, { onSuccess: () => { - return queryClient.invalidateQueries( - accountKeys.me(user?.address as string), - ); + return queryClient.invalidateQueries({ + queryKey: accountKeys.me(user?.address as string), + }); }, }, ); @@ -723,8 +728,8 @@ export function useCreateApiKey() { const { user } = useLoggedInUser(); const queryClient = useQueryClient(); - return useMutation( - async (input: CreateKeyInput) => { + return useMutation({ + mutationFn: async (input: CreateKeyInput) => { invariant(user?.address, "walletAddress is required"); const res = await fetch(`${THIRDWEB_API_HOST}/v1/keys`, { @@ -743,14 +748,13 @@ export function useCreateApiKey() { return json.data as ApiKey; }, - { - onSuccess: () => { - return queryClient.invalidateQueries( - apiKeys.keys(user?.address as string), - ); - }, + + onSuccess: () => { + return queryClient.invalidateQueries({ + queryKey: apiKeys.keys(user?.address as string), + }); }, - ); + }); } export function useUpdateApiKey() { @@ -780,9 +784,9 @@ export function useUpdateApiKey() { }, { onSuccess: () => { - return queryClient.invalidateQueries( - apiKeys.keys(user?.address as string), - ); + return queryClient.invalidateQueries({ + queryKey: apiKeys.keys(user?.address as string), + }); }, }, ); @@ -814,9 +818,9 @@ export function useRevokeApiKey() { }, { onSuccess: () => { - return queryClient.invalidateQueries( - apiKeys.keys(user?.address as string), - ); + return queryClient.invalidateQueries({ + queryKey: apiKeys.keys(user?.address as string), + }); }, }, ); @@ -869,7 +873,9 @@ export const useUpdatePolicies = () => { }, { onSuccess: (_, variables) => { - return queryClient.invalidateQueries(["policies", variables.serviceId]); + return queryClient.invalidateQueries({ + queryKey: ["policies", variables.serviceId], + }); }, }, ); @@ -906,9 +912,11 @@ export function useRevokeAuthorizedWallet() { }, { onSuccess: () => { - return queryClient.invalidateQueries( - authorizedWallets.authorizedWallets(user?.address as string), - ); + return queryClient.invalidateQueries({ + queryKey: authorizedWallets.authorizedWallets( + user?.address as string, + ), + }); }, }, ); @@ -936,7 +944,7 @@ export function useAuthorizedWallets() { return json.data as AuthorizedWallet[]; }, enabled: !!user?.address && isLoggedIn, - cacheTime: 0, + gcTime: 0, }); } diff --git a/apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts b/apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts index 8d46582df..f047ea79a 100644 --- a/apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts +++ b/apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts @@ -191,24 +191,26 @@ interface UpdateVersionInput { } export function useEngineUpdateVersion() { - return useMutation(async (input: UpdateVersionInput) => { - invariant(input.engineId, "engineId is required"); + return useMutation({ + mutationFn: async (input: UpdateVersionInput) => { + invariant(input.engineId, "engineId is required"); - const res = await fetch(`${THIRDWEB_API_HOST}/v1/engine/update-version`, { - method: "POST", + const res = await fetch(`${THIRDWEB_API_HOST}/v1/engine/update-version`, { + method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - engineId: input.engineId, - }), - }); - // we never use the response body - res.body?.cancel(); - if (!res.ok) { - throw new Error(`Unexpected status ${res.status}: ${await res.text()}`); - } + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + engineId: input.engineId, + }), + }); + // we never use the response body + res.body?.cancel(); + if (!res.ok) { + throw new Error(`Unexpected status ${res.status}: ${await res.text()}`); + } + }, }); } @@ -216,8 +218,8 @@ export function useEngineRemoveFromDashboard() { const { user } = useLoggedInUser(); const queryClient = useQueryClient(); - return useMutation( - async (instanceId: string) => { + return useMutation({ + mutationFn: async (instanceId: string) => { invariant(instanceId, "instance is required"); const res = await fetch(`${THIRDWEB_API_HOST}/v1/engine/${instanceId}`, { @@ -229,14 +231,13 @@ export function useEngineRemoveFromDashboard() { throw new Error(`Unexpected status ${res.status}: ${await res.text()}`); } }, - { - onSuccess: () => { - return queryClient.invalidateQueries( - engineKeys.instances(user?.address as string), - ); - }, + + onSuccess: () => { + return queryClient.invalidateQueries({ + queryKey: engineKeys.instances(user?.address as string), + }); }, - ); + }); } export interface RemoveCloudHostedInput { @@ -249,8 +250,12 @@ export function useEngineRemoveCloudHosted() { const { user } = useLoggedInUser(); const queryClient = useQueryClient(); - return useMutation( - async ({ instanceId, reason, feedback }: RemoveCloudHostedInput) => { + return useMutation({ + mutationFn: async ({ + instanceId, + reason, + feedback, + }: RemoveCloudHostedInput) => { const res = await fetch( `${THIRDWEB_API_HOST}/v1/engine/${instanceId}/remove-cloud-hosted`, { @@ -268,14 +273,13 @@ export function useEngineRemoveCloudHosted() { throw new Error(`Unexpected status ${res.status}: ${await res.text()}`); } }, - { - onSuccess: () => { - return queryClient.invalidateQueries( - engineKeys.instances(user?.address as string), - ); - }, + + onSuccess: () => { + return queryClient.invalidateQueries({ + queryKey: engineKeys.instances(user?.address as string), + }); }, - ); + }); } export interface EditEngineInstanceInput { @@ -288,8 +292,8 @@ export function useEngineEditInstance() { const { user } = useLoggedInUser(); const queryClient = useQueryClient(); - return useMutation( - async ({ instanceId, name, url }: EditEngineInstanceInput) => { + return useMutation({ + mutationFn: async ({ instanceId, name, url }: EditEngineInstanceInput) => { const res = await fetch(`${THIRDWEB_API_HOST}/v1/engine/${instanceId}`, { method: "PUT", @@ -304,14 +308,13 @@ export function useEngineEditInstance() { throw new Error(`Unexpected status ${res.status}: ${await res.text()}`); } }, - { - onSuccess: () => { - return queryClient.invalidateQueries( - engineKeys.instances(user?.address as string), - ); - }, + + onSuccess: () => { + return queryClient.invalidateQueries({ + queryKey: engineKeys.instances(user?.address as string), + }); }, - ); + }); } export type Transaction = { @@ -586,7 +589,9 @@ export function useEngineAddKeypair(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.keypairs(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.keypairs(instance), + }); }, }, ); @@ -619,7 +624,9 @@ export function useEngineRemoveKeypair(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.keypairs(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.keypairs(instance), + }); }, }, ); @@ -684,7 +691,9 @@ export function useEngineCreateRelayer(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.relayers(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.relayers(instance), + }); }, }, ); @@ -717,7 +726,9 @@ export function useEngineRevokeRelayer(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.relayers(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.relayers(instance), + }); }, }, ); @@ -755,7 +766,9 @@ export function useEngineUpdateRelayer(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.relayers(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.relayers(instance), + }); }, }, ); @@ -833,7 +846,9 @@ export function useEngineSetWalletConfig(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.walletConfig(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.walletConfig(instance), + }); }, }, ); @@ -866,9 +881,9 @@ export function useEngineCreateBackendWallet(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries( - engineKeys.backendWallets(instance), - ); + return queryClient.invalidateQueries({ + queryKey: engineKeys.backendWallets(instance), + }); }, }, ); @@ -902,9 +917,9 @@ export function useEngineUpdateBackendWallet(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries( - engineKeys.backendWallets(instance), - ); + return queryClient.invalidateQueries({ + queryKey: engineKeys.backendWallets(instance), + }); }, }, ); @@ -953,9 +968,9 @@ export function useEngineImportBackendWallet(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries( - engineKeys.backendWallets(instance), - ); + return queryClient.invalidateQueries({ + queryKey: engineKeys.backendWallets(instance), + }); }, }, ); @@ -984,7 +999,9 @@ export function useEngineGrantPermissions(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.permissions(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.permissions(instance), + }); }, }, ); @@ -1017,7 +1034,9 @@ export function useEngineRevokePermissions(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.permissions(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.permissions(instance), + }); }, }, ); @@ -1050,7 +1069,9 @@ export function useEngineCreateAccessToken(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.accessTokens(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.accessTokens(instance), + }); }, }, ); @@ -1083,7 +1104,9 @@ export function useEngineRevokeAccessToken(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.accessTokens(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.accessTokens(instance), + }); }, }, ); @@ -1117,7 +1140,9 @@ export function useEngineUpdateAccessToken(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.accessTokens(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.accessTokens(instance), + }); }, }, ); @@ -1152,7 +1177,9 @@ export function useEngineCreateWebhook(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.webhooks(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.webhooks(instance), + }); }, }, ); @@ -1185,7 +1212,9 @@ export function useEngineRevokeWebhook(instance: string) { }, { onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.webhooks(instance)); + return queryClient.invalidateQueries({ + queryKey: engineKeys.webhooks(instance), + }); }, }, ); @@ -1202,31 +1231,33 @@ type SendTokensInput = { export function useEngineSendTokens(instance: string) { const token = useLoggedInUser().user?.jwt ?? null; - return useMutation(async (input: SendTokensInput) => { - invariant(instance, "instance is required"); + return useMutation({ + mutationFn: async (input: SendTokensInput) => { + invariant(instance, "instance is required"); - const res = await fetch( - `${instance}backend-wallet/${input.chainId}/transfer`, - { - method: "POST", - headers: { - ...getEngineRequestHeaders(token), - "x-backend-wallet-address": input.fromAddress, + const res = await fetch( + `${instance}backend-wallet/${input.chainId}/transfer`, + { + method: "POST", + headers: { + ...getEngineRequestHeaders(token), + "x-backend-wallet-address": input.fromAddress, + }, + body: JSON.stringify({ + to: input.toAddress, + amount: input.amount.toString(), + currencyAddress: input.currencyAddress, + }), }, - body: JSON.stringify({ - to: input.toAddress, - amount: input.amount.toString(), - currencyAddress: input.currencyAddress, - }), - }, - ); - const json = await res.json(); + ); + const json = await res.json(); - if (json.error) { - throw new Error(json.error.message); - } + if (json.error) { + throw new Error(json.error.message); + } - return json.result; + return json.result; + }, }); } @@ -1257,8 +1288,8 @@ export function useEngineSetCorsConfiguration(instance: string) { const queryClient = useQueryClient(); const token = useLoggedInUser().user?.jwt ?? null; - return useMutation( - async (input: SetCorsUrlInput) => { + return useMutation({ + mutationFn: async (input: SetCorsUrlInput) => { invariant(instance, "instance is required"); const res = await fetch(`${instance}configuration/cors`, { @@ -1274,12 +1305,13 @@ export function useEngineSetCorsConfiguration(instance: string) { return json.result; }, - { - onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.corsUrls(instance)); - }, + + onSuccess: () => { + return queryClient.invalidateQueries({ + queryKey: engineKeys.corsUrls(instance), + }); }, - ); + }); } export function useEngineIpAllowlistConfiguration(instance: string) { @@ -1314,8 +1346,8 @@ export function useEngineSetIpAllowlistConfiguration(instance: string) { const queryClient = useQueryClient(); const token = useLoggedInUser().user?.jwt ?? null; - return useMutation( - async (input: SetIpAllowlistInput) => { + return useMutation({ + mutationFn: async (input: SetIpAllowlistInput) => { invariant(instance, "instance is required"); const res = await fetch(`${instance}configuration/ip-allowlist`, { @@ -1331,12 +1363,13 @@ export function useEngineSetIpAllowlistConfiguration(instance: string) { return json.result; }, - { - onSuccess: () => { - return queryClient.invalidateQueries(engineKeys.ipAllowlist(instance)); - }, + + onSuccess: () => { + return queryClient.invalidateQueries({ + queryKey: engineKeys.ipAllowlist(instance), + }); }, - ); + }); } export interface EngineContractSubscription { @@ -1386,8 +1419,8 @@ export function useEngineAddContractSubscription(instance: string) { const queryClient = useQueryClient(); const token = useLoggedInUser().user?.jwt ?? null; - return useMutation( - async (input: AddContractSubscriptionInput) => { + return useMutation({ + mutationFn: async (input: AddContractSubscriptionInput) => { invariant(instance, "instance is required"); const res = await fetch(`${instance}contract-subscriptions/add`, { @@ -1403,14 +1436,13 @@ export function useEngineAddContractSubscription(instance: string) { return json.result; }, - { - onSuccess: () => { - return queryClient.invalidateQueries( - engineKeys.contractSubscriptions(instance), - ); - }, + + onSuccess: () => { + return queryClient.invalidateQueries({ + queryKey: engineKeys.contractSubscriptions(instance), + }); }, - ); + }); } interface RemoveContractSubscriptionInput { @@ -1421,8 +1453,8 @@ export function useEngineRemoveContractSubscription(instance: string) { const queryClient = useQueryClient(); const token = useLoggedInUser().user?.jwt ?? null; - return useMutation( - async (input: RemoveContractSubscriptionInput) => { + return useMutation({ + mutationFn: async (input: RemoveContractSubscriptionInput) => { invariant(instance, "instance is required"); const res = await fetch(`${instance}contract-subscriptions/remove`, { @@ -1438,14 +1470,13 @@ export function useEngineRemoveContractSubscription(instance: string) { return json.result; }, - { - onSuccess: () => { - return queryClient.invalidateQueries( - engineKeys.contractSubscriptions(instance), - ); - }, + + onSuccess: () => { + return queryClient.invalidateQueries({ + queryKey: engineKeys.contractSubscriptions(instance), + }); }, - ); + }); } export function useEngineSubscriptionsLastBlock( diff --git a/apps/dashboard/src/@3rdweb-sdk/react/hooks/useLoggedInUser.ts b/apps/dashboard/src/@3rdweb-sdk/react/hooks/useLoggedInUser.ts index ff8160c23..e15a8a54d 100644 --- a/apps/dashboard/src/@3rdweb-sdk/react/hooks/useLoggedInUser.ts +++ b/apps/dashboard/src/@3rdweb-sdk/react/hooks/useLoggedInUser.ts @@ -3,7 +3,7 @@ import { useDashboardRouter } from "@/lib/DashboardRouter"; import { useQuery } from "@tanstack/react-query"; import type { EnsureLoginResponse } from "app/api/auth/ensure-login/route"; import { usePathname } from "next/navigation"; -import { useRef } from "react"; +import { useEffect, useRef } from "react"; import { useActiveAccount, useActiveWalletConnectionStatus, @@ -63,20 +63,23 @@ export function useLoggedInUser(): { return (await res.json()) as EnsureLoginResponse; }, - onSuccess: (data) => { - if (data.redirectTo) { - router.replace(data.redirectTo); - } - if (data.jwt) { - // necessary for legacy things for now (SDK picks it up from there) - // eslint-disable-next-line react-compiler/react-compiler - window.TW_AUTH_TOKEN = data.jwt; - } else { - window.TW_AUTH_TOKEN = undefined; - } - }, }); + // legit use-case for now + // eslint-disable-next-line no-restricted-syntax + useEffect(() => { + if (query.data?.redirectTo) { + router.replace(query.data.redirectTo); + } + if (query.data?.jwt) { + // necessary for legacy things for now (SDK picks it up from there) + // eslint-disable-next-line react-compiler/react-compiler + window.TW_AUTH_TOKEN = query.data.jwt; + } else { + window.TW_AUTH_TOKEN = undefined; + } + }, [query.data?.redirectTo, query.data?.jwt, router]); + // if we are "disconnected" we are not logged in if (connectionStatus === "disconnected") { return { diff --git a/apps/dashboard/src/@3rdweb-sdk/react/hooks/useRegistry.ts b/apps/dashboard/src/@3rdweb-sdk/react/hooks/useRegistry.ts index 263f1cbbc..7b5b51879 100644 --- a/apps/dashboard/src/@3rdweb-sdk/react/hooks/useRegistry.ts +++ b/apps/dashboard/src/@3rdweb-sdk/react/hooks/useRegistry.ts @@ -88,8 +88,8 @@ export function useRemoveContractMutation() { const { chainIdToChainRecord } = useAllChainsData(); const queryClient = useQueryClient(); const account = useActiveAccount(); - return useMutation( - async (data: RemoveContractParams) => { + return useMutation({ + mutationFn: async (data: RemoveContractParams) => { invariant(chainIdToChainRecord, "chains not initialzed yet"); invariant(data.chainId, "chainId not provided"); invariant(account, "No wallet connected"); @@ -111,12 +111,13 @@ export function useRemoveContractMutation() { }, }); }, - { - onSettled: () => { - return queryClient.invalidateQueries(["dashboard-registry"]); - }, + + onSettled: () => { + return queryClient.invalidateQueries({ + queryKey: ["dashboard-registry"], + }); }, - ); + }); } type AddContractParams = { @@ -129,8 +130,8 @@ export function useAddContractMutation() { const queryClient = useQueryClient(); - return useMutation( - async (data: AddContractParams) => { + return useMutation({ + mutationFn: async (data: AddContractParams) => { invariant(account, "cannot add a contract without an address"); return await addContractToMultiChainRegistry( @@ -142,10 +143,11 @@ export function useAddContractMutation() { 300000n, ); }, - { - onSettled: () => { - return queryClient.invalidateQueries(["dashboard-registry"]); - }, + + onSettled: () => { + return queryClient.invalidateQueries({ + queryKey: ["dashboard-registry"], + }); }, - ); + }); } diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/FaucetButton.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/FaucetButton.tsx index 37e6c7fa1..811233f0d 100644 --- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/FaucetButton.tsx +++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/FaucetButton.tsx @@ -92,10 +92,9 @@ export function FaucetButton({ }); }, onSettled: () => { - return queryClient.invalidateQueries([ - "testnet-faucet-can-claim", - chainId, - ]); + return queryClient.invalidateQueries({ + queryKey: ["testnet-faucet-can-claim", chainId], + }); }, }); @@ -175,7 +174,7 @@ export function FaucetButton({ }); }} > - {claimMutation.isLoading ? ( + {claimMutation.isPending ? ( <> Claiming diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/add-chain-to-wallet.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/add-chain-to-wallet.tsx index 77bc9f1cc..22feee531 100644 --- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/add-chain-to-wallet.tsx +++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/add-chain-to-wallet.tsx @@ -30,7 +30,7 @@ export const AddChainToWallet: React.FC = (props) => { }, }); - const [debouncedLoading] = useDebounce(switchChainMutation.isLoading, 50); + const [debouncedLoading] = useDebounce(switchChainMutation.isPending, 50); const disabled = debouncedLoading || activeWalletChainId === props.chain?.id; diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx index 43445c336..657ec93db 100644 --- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx +++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx @@ -7,13 +7,10 @@ import { thirdwebClient } from "@/constants/client"; import { isProd } from "@/constants/env"; import { useQuery } from "@tanstack/react-query"; import { CircleCheck, XIcon } from "lucide-react"; -import { useState } from "react"; import { hostnameEndsWith } from "utils/url"; import { PrimaryInfoItem } from "../server/primary-info-item"; function useChainStatswithRPC(_rpcUrl: string) { - const [shouldRefetch, setShouldRefetch] = useState(true); - let rpcUrl = _rpcUrl.replace( // eslint-disable-next-line no-template-curly-in-string "${THIRDWEB_API_KEY}", @@ -49,12 +46,14 @@ function useChainStatswithRPC(_rpcUrl: string) { blockNumber: Number.parseInt(json.result, 16), }; }, - refetchInterval: shouldRefetch ? 5 * 1000 : undefined, + refetchInterval: (query) => { + if (query.state.error) { + return false; + } + return 5 * 1000; + }, enabled: !!rpcUrl, refetchOnWindowFocus: false, - onError: () => { - setShouldRefetch(false); - }, }); } diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/chain-header.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/chain-header.tsx index a3b3acd8f..d2013b4af 100644 --- a/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/chain-header.tsx +++ b/apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/chain-header.tsx @@ -20,7 +20,6 @@ export function ChainHeader(props: ChainHeaderProps) { // force the banner image to be 4:1 aspect ratio and full-width on mobile devices
{!props.headerImageUrl &&
} - )} - {/* below header */}
{/* chain logo */} diff --git a/apps/dashboard/src/app/(dashboard)/(chain)/components/client/star-button.tsx b/apps/dashboard/src/app/(dashboard)/(chain)/components/client/star-button.tsx index b603fe1f1..e81e5af62 100644 --- a/apps/dashboard/src/app/(dashboard)/(chain)/components/client/star-button.tsx +++ b/apps/dashboard/src/app/(dashboard)/(chain)/components/client/star-button.tsx @@ -91,7 +91,7 @@ export function StarButton(props: { }} disabled={ !loggedInUser.user?.address || - mutation.isLoading || + mutation.isPending || favChainsQuery.isLoading } > diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/add-partner-form.client.tsx b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/add-partner-form.client.tsx index 229a55632..92777a603 100644 --- a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/add-partner-form.client.tsx +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/add-partner-form.client.tsx @@ -31,7 +31,7 @@ export function AddPartnerForm({ ecosystem }: { ecosystem: Ecosystem }) { resolver: zodResolver(partnerFormSchema), }); - const { addPartner, isLoading } = useAddPartner({ + const { mutateAsync: addPartner, isPending } = useAddPartner({ onSuccess: () => { form.reset(); }, @@ -182,7 +182,7 @@ export function AddPartnerForm({ ecosystem }: { ecosystem: Ecosystem }) { />
diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/server/partners-table.tsx b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/server/partners-table.tsx index 5a361ad00..089b2c821 100644 --- a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/server/partners-table.tsx +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/server/partners-table.tsx @@ -69,13 +69,14 @@ function EcosystemRow(props: { partner: Partner; ecosystem: Ecosystem; }) { - const { deletePartner, isLoading: isDeleting } = useDeletePartner({ - onError: (error) => { - const message = - error instanceof Error ? error.message : "Failed to delete partner"; - toast.error(message); - }, - }); + const { mutateAsync: deletePartner, isPending: isDeleting } = + useDeletePartner({ + onError: (error) => { + const message = + error instanceof Error ? error.message : "Failed to delete partner"; + toast.error(message); + }, + }); return ( => { if (!isLoggedIn || !user?.jwt) { @@ -74,11 +74,9 @@ export function useAddPartner( return data; }, onSuccess: async (partner, variables, context) => { - await queryClient.invalidateQueries([ - "ecosystem", - variables.ecosystem.id, - "partners", - ]); + await queryClient.invalidateQueries({ + queryKey: ["ecosystem", variables.ecosystem.id, "partners"], + }); if (onSuccess) { return onSuccess(partner, variables, context); } @@ -86,6 +84,4 @@ export function useAddPartner( }, ...queryOptions, }); - - return { addPartner, isLoading }; } diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-delete-partner.ts b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-delete-partner.ts index 351ca2717..3548999e5 100644 --- a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-delete-partner.ts +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-delete-partner.ts @@ -21,7 +21,7 @@ export function useDeletePartner( const { isLoggedIn, user } = useLoggedInUser(); const queryClient = useQueryClient(); - const { mutateAsync: deletePartner, isLoading } = useMutation({ + return useMutation({ // Returns true on success mutationFn: async (params: DeletePartnerParams): Promise => { if (!isLoggedIn || !user?.jwt) { @@ -58,11 +58,9 @@ export function useDeletePartner( return true; }, onSuccess: async (partner, variables, context) => { - await queryClient.invalidateQueries([ - "ecosystem", - variables.ecosystem.id, - "partners", - ]); + await queryClient.invalidateQueries({ + queryKey: ["ecosystem", variables.ecosystem.id, "partners"], + }); if (onSuccess) { return onSuccess(partner, variables, context); } @@ -70,6 +68,4 @@ export function useDeletePartner( }, ...queryOptions, }); - - return { deletePartner, isLoading }; } diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-update-ecosystem.ts b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-update-ecosystem.ts index b7467a69c..d5d1a52d4 100644 --- a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-update-ecosystem.ts +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-update-ecosystem.ts @@ -21,11 +21,7 @@ export function useUpdateEcosystem( const { isLoggedIn, user } = useLoggedInUser(); const queryClient = useQueryClient(); - const { - mutateAsync: updateEcosystem, - isLoading, - variables, - } = useMutation({ + return useMutation({ // Returns true if the update was successful mutationFn: async (params: UpdateEcosystemParams): Promise => { if (!isLoggedIn || !user?.jwt) { @@ -65,7 +61,9 @@ export function useUpdateEcosystem( return true; }, onSuccess: async (partner, variables, context) => { - await queryClient.invalidateQueries(["ecosystems"]); + await queryClient.invalidateQueries({ + queryKey: ["ecosystems"], + }); if (onSuccess) { return onSuccess(partner, variables, context); } @@ -73,6 +71,4 @@ export function useUpdateEcosystem( }, ...queryOptions, }); - - return { updateEcosystem, isLoading, variables }; } diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-update-partner.ts b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-update-partner.ts index 6360fde78..d74750501 100644 --- a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-update-partner.ts +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-update-partner.ts @@ -25,7 +25,7 @@ export function useUpdatePartner( const { isLoggedIn, user } = useLoggedInUser(); const queryClient = useQueryClient(); - const { mutateAsync: updatePartner, isLoading } = useMutation({ + return useMutation({ // Returns the created partner object mutationFn: async (params: UpdatePartnerParams): Promise => { if (!isLoggedIn || !user?.jwt) { @@ -73,11 +73,9 @@ export function useUpdatePartner( return data; }, onSuccess: async (partner, variables, context) => { - await queryClient.invalidateQueries([ - "ecosystem", - variables.ecosystem.id, - "partners", - ]); + await queryClient.invalidateQueries({ + queryKey: ["ecosystem", variables.ecosystem.id, "partners"], + }); if (onSuccess) { return onSuccess(partner, variables, context); } @@ -85,6 +83,4 @@ export function useUpdatePartner( }, ...queryOptions, }); - - return { updatePartner, isLoading }; } diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/components/client/create-ecosystem-form.client.tsx b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/components/client/create-ecosystem-form.client.tsx index efdad3db4..7a661724f 100644 --- a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/components/client/create-ecosystem-form.client.tsx +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/components/client/create-ecosystem-form.client.tsx @@ -59,7 +59,7 @@ export function CreateEcosystemForm(props: { }, }); - const { createEcosystem, isLoading } = useCreateEcosystem({ + const { mutateAsync: createEcosystem, isPending } = useCreateEcosystem({ onError: (error) => { const message = error instanceof Error ? error.message : "Failed to create ecosystem"; @@ -181,9 +181,9 @@ export function CreateEcosystemForm(props: { type="submit" variant="primary" className="w-full" - disabled={isLoading} + disabled={isPending} > - {isLoading && } + {isPending && } Create )} diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/hooks/use-create-ecosystem.ts b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/hooks/use-create-ecosystem.ts index 529577d7d..c983c2bc9 100644 --- a/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/hooks/use-create-ecosystem.ts +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/hooks/use-create-ecosystem.ts @@ -24,7 +24,7 @@ export function useCreateEcosystem( const { isLoggedIn } = useLoggedInUser(); const queryClient = useQueryClient(); - const { mutateAsync: createEcosystem, isLoading } = useMutation({ + return useMutation({ // Returns the created ecosystem slug mutationFn: async (params: CreateEcosystemParams): Promise => { if (!isLoggedIn) { @@ -75,10 +75,10 @@ export function useCreateEcosystem( if (onSuccess) { await onSuccess(id, variables, context); } - return queryClient.invalidateQueries(["ecosystems"]); + return queryClient.invalidateQueries({ + queryKey: ["ecosystems"], + }); }, ...queryOptions, }); - - return { createEcosystem, isLoading }; } diff --git a/apps/dashboard/src/app/(dashboard)/dashboard/connect/pay/components/webhooks.client.tsx b/apps/dashboard/src/app/(dashboard)/dashboard/connect/pay/components/webhooks.client.tsx index f14b19fad..1750fe5da 100644 --- a/apps/dashboard/src/app/(dashboard)/dashboard/connect/pay/components/webhooks.client.tsx +++ b/apps/dashboard/src/app/(dashboard)/dashboard/connect/pay/components/webhooks.client.tsx @@ -177,7 +177,9 @@ function CreateWebhookButton(props: PropsWithChildren) { return json.result as string; }, onSuccess: () => { - return queryClient.invalidateQueries(["webhooks", props.clientId]); + return queryClient.invalidateQueries({ + queryKey: ["webhooks", props.clientId], + }); }, }); return ( @@ -264,7 +266,7 @@ function CreateWebhookButton(props: PropsWithChildren) { - @@ -293,7 +295,9 @@ function DeleteWebhookButton( return json.result as string; }, onSuccess: () => { - return queryClient.invalidateQueries(["webhooks", props.clientId]); + return queryClient.invalidateQueries({ + queryKey: ["webhooks", props.clientId], + }); }, }); return ( @@ -325,7 +329,7 @@ function DeleteWebhookButton( }, ); }} - disabled={deleteMutation.isLoading} + disabled={deleteMutation.isPending} > Yes, Delete Webhook diff --git a/apps/dashboard/src/app/account/settings/AccountSettingsPageUI.tsx b/apps/dashboard/src/app/account/settings/AccountSettingsPageUI.tsx index f228a7a13..72601af54 100644 --- a/apps/dashboard/src/app/account/settings/AccountSettingsPageUI.tsx +++ b/apps/dashboard/src/app/account/settings/AccountSettingsPageUI.tsx @@ -85,7 +85,7 @@ function AccountAvatarFormControl() { saveButton={{ onClick: handleSave, disabled: false, - isLoading: updateAvatarMutation.isLoading, + isLoading: updateAvatarMutation.isPending, }} noPermissionText={undefined} errorText={undefined} @@ -143,7 +143,7 @@ function AccountNameFormControl(props: { saveButton={{ onClick: handleSave, disabled: accountName.length === 0, - isLoading: updateAccountNameMutation.isLoading, + isLoading: updateAccountNameMutation.isPending, }} errorText={undefined} noPermissionText={undefined} // TODO @@ -191,7 +191,7 @@ function DeleteAccountCard() { description={description} buttonLabel={title} buttonOnClick={handleDelete} - isLoading={deleteAccount.isLoading} + isLoading={deleteAccount.isPending} confirmationDialog={{ title: "Are you sure you want to delete your account?", description: @@ -321,10 +321,10 @@ function EmailUpdateDialog(props: { diff --git a/apps/dashboard/src/app/components/Header/DashboardHeader.tsx b/apps/dashboard/src/app/components/Header/DashboardHeader.tsx index e058f08b8..7b61783d1 100644 --- a/apps/dashboard/src/app/components/Header/DashboardHeader.tsx +++ b/apps/dashboard/src/app/components/Header/DashboardHeader.tsx @@ -35,7 +35,6 @@ export function DashboardHeader() { ))}
- {/* Right */}
diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/billing/BillingSettingsPage.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/billing/BillingSettingsPage.tsx index 17400005b..012d1079c 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/billing/BillingSettingsPage.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/billing/BillingSettingsPage.tsx @@ -6,11 +6,11 @@ import { Billing } from "components/settings/Account/Billing"; export const SettingsBillingPage = () => { const meQuery = useAccount({ - refetchInterval: (account) => + refetchInterval: (query) => [ AccountStatus.InvalidPayment, AccountStatus.InvalidPaymentMethod, - ].includes(account?.status as AccountStatus) + ].includes(query.state?.status as AccountStatus) ? 1000 : false, }); diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/GeneralSettingsPage.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/GeneralSettingsPage.tsx index 0801ce751..babd164e3 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/GeneralSettingsPage.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/GeneralSettingsPage.tsx @@ -63,7 +63,7 @@ function TeamNameFormControl(props: { saveButton={{ onClick: handleSave, disabled: teamName.length === 0, - isLoading: updateTeamMutation.isLoading, + isLoading: updateTeamMutation.isPending, }} errorText={undefined} noPermissionText={undefined} // TODO @@ -121,7 +121,7 @@ function TeamSlugFormControl(props: { saveButton={{ onClick: handleSave, disabled: teamSlug.length === 0, - isLoading: updateTeamMutation.isLoading, + isLoading: updateTeamMutation.isPending, }} noPermissionText={undefined} // TODO > @@ -168,7 +168,7 @@ function TeamAvatarFormControl() { saveButton={{ onClick: handleSave, disabled: false, - isLoading: updateTeamAvatarMutation.isLoading, + isLoading: updateTeamAvatarMutation.isPending, }} noPermissionText={undefined} // TODO errorText={undefined} @@ -250,7 +250,7 @@ export function LeaveTeamCard(props: { description={description} buttonLabel={title} buttonOnClick={handleLeave} - isLoading={leaveTeam.isLoading} + isLoading={leaveTeam.isPending} confirmationDialog={{ title: `Are you sure you want to leave team "${props.teamName}" ?`, description: @@ -311,7 +311,7 @@ export function DeleteTeamCard(props: { description={description} buttonLabel={title} buttonOnClick={handleDelete} - isLoading={deleteTeam.isLoading} + isLoading={deleteTeam.isPending} confirmationDialog={{ title: `Are you sure you want to delete team "${props.teamName}" ?`, description: description, diff --git a/apps/dashboard/src/app/team/components/TeamHeader/TeamSelectionUI.tsx b/apps/dashboard/src/app/team/components/TeamHeader/TeamSelectionUI.tsx index 07e499555..6ac4a697f 100644 --- a/apps/dashboard/src/app/team/components/TeamHeader/TeamSelectionUI.tsx +++ b/apps/dashboard/src/app/team/components/TeamHeader/TeamSelectionUI.tsx @@ -31,9 +31,7 @@ export function TeamSelectionUI(props: { value={searchTeamTerm} onValueChange={setSearchTeamTerm} /> - -
- {/* TODO - what do we do on this button click? */} {/* Bottom */} {teamPlan && teamPlan !== "pro" && ( diff --git a/apps/dashboard/src/components/app-layouts/app.tsx b/apps/dashboard/src/components/app-layouts/app.tsx index 469740db2..3238db6b9 100644 --- a/apps/dashboard/src/components/app-layouts/app.tsx +++ b/apps/dashboard/src/components/app-layouts/app.tsx @@ -7,7 +7,7 @@ import { CustomConnectWallet } from "@3rdweb-sdk/react/components/connect-wallet import { Flex, SimpleGrid } from "@chakra-ui/react"; import { type DehydratedState, - Hydrate, + HydrationBoundary, QueryClient, QueryClientProvider, } from "@tanstack/react-query"; @@ -38,7 +38,7 @@ interface AppLayoutProps extends AppShellProps { export const AppLayout: ComponentWithChildren = (props) => { // has to be constructed in here because it may otherwise share state between SSR'd pages - const [queryClient] = useState(() => new QueryClient()); + const [queryClient] = useState(() => new QueryClient({})); // will be deleted as part of: https://github.com/thirdweb-dev/dashboard/pull/2648 // eslint-disable-next-line no-restricted-syntax @@ -54,7 +54,7 @@ export const AppLayout: ComponentWithChildren = (props) => { return ( - + @@ -74,7 +74,7 @@ export const AppLayout: ComponentWithChildren = (props) => { - + ); }; diff --git a/apps/dashboard/src/components/buttons/MismatchButton.tsx b/apps/dashboard/src/components/buttons/MismatchButton.tsx index dc4194738..cedb37f7b 100644 --- a/apps/dashboard/src/components/buttons/MismatchButton.tsx +++ b/apps/dashboard/src/components/buttons/MismatchButton.tsx @@ -337,7 +337,6 @@ function NoFundsDialogContent(props: {
)} - {/* Footer */}
diff --git a/apps/dashboard/src/components/cmd-k-search/index.tsx b/apps/dashboard/src/components/cmd-k-search/index.tsx index 91c20ac08..116e70b20 100644 --- a/apps/dashboard/src/components/cmd-k-search/index.tsx +++ b/apps/dashboard/src/components/cmd-k-search/index.tsx @@ -16,6 +16,8 @@ import { useDashboardRouter } from "@/lib/DashboardRouter"; import { cn } from "@/lib/utils"; import { type QueryClient, + keepPreviousData, + queryOptions, useQuery, useQueryClient, } from "@tanstack/react-query"; @@ -38,7 +40,7 @@ function contractTypesenseSearchQuery( queryClient: QueryClient, trackEvent: ReturnType, ) { - return { + return queryOptions({ queryKey: ["typesense-contract-search", { search: searchQuery }], queryFn: async () => { trackEvent({ @@ -55,26 +57,8 @@ function contractTypesenseSearchQuery( }); }, enabled: !!searchQuery && !!queryClient && !!typesenseApiKey, - onSuccess: (d: unknown) => { - trackEvent({ - category: TRACKING_CATEGORY, - action: "query", - label: "success", - searchQuery, - response: d, - }); - }, - onError: (err: unknown) => { - trackEvent({ - category: TRACKING_CATEGORY, - action: "query", - label: "failure", - searchQuery, - error: err, - }); - }, - keepPreviousData: true, - }; + placeholderData: keepPreviousData, + }); } export const CmdKSearchModal = (props: { @@ -103,7 +87,7 @@ export const CmdKSearchModal = (props: { // debounce 500ms const [debouncedSearchValue] = useDebounce(searchValue, 500); - const typesenseSearchQuery = useQuery( + const typesenseSearchQuery = useQuery( contractTypesenseSearchQuery(debouncedSearchValue, queryClient, trackEvent), ); diff --git a/apps/dashboard/src/components/configure-networks/Form/IconUpload.tsx b/apps/dashboard/src/components/configure-networks/Form/IconUpload.tsx index 3302f3bbe..61340dc9f 100644 --- a/apps/dashboard/src/components/configure-networks/Form/IconUpload.tsx +++ b/apps/dashboard/src/components/configure-networks/Form/IconUpload.tsx @@ -24,7 +24,9 @@ export const IconUpload: React.FC<{ onUpload: (url: string) => void }> = ({ onSuccess([uri]) { onUpload(uri); // also refetch the files list - queryClient.invalidateQueries([PINNED_FILES_QUERY_KEY_ROOT]); + queryClient.invalidateQueries({ + queryKey: [PINNED_FILES_QUERY_KEY_ROOT], + }); }, onError(error) { console.error(error); @@ -36,7 +38,7 @@ export const IconUpload: React.FC<{ onUpload: (url: string) => void }> = ({ return ( = (props) => { {...props} canEditAdvancedFeatures={dashboardAccount.advancedEnabled} updateApiKey={handleAPIKeyUpdate} - isUpdating={mutation.isLoading} + isUpdating={mutation.isPending} /> ); }; diff --git a/apps/dashboard/src/components/engine/badges/version.tsx b/apps/dashboard/src/components/engine/badges/version.tsx index 7fe53c6d3..b7e5feb67 100644 --- a/apps/dashboard/src/components/engine/badges/version.tsx +++ b/apps/dashboard/src/components/engine/badges/version.tsx @@ -153,7 +153,7 @@ const UpdateVersionModal = (props: { variant="primary" className="gap-2" > - {updateEngine.isLoading ? ( + {updateEngine.isPending ? ( ) : ( diff --git a/apps/dashboard/src/components/engine/configuration/local-config.tsx.tsx b/apps/dashboard/src/components/engine/configuration/local-config.tsx.tsx index 0b1ac387e..60d59d6a5 100644 --- a/apps/dashboard/src/components/engine/configuration/local-config.tsx.tsx +++ b/apps/dashboard/src/components/engine/configuration/local-config.tsx.tsx @@ -13,7 +13,7 @@ interface LocalConfigProps { export const LocalConfig: React.FC = ({ instanceUrl }) => { const { data: walletConfig } = useEngineWalletConfig(instanceUrl); - const { mutate: setLocalConfig, isLoading } = + const { mutate: setLocalConfig, isPending } = useEngineSetWalletConfig(instanceUrl); const trackEvent = useTrack(); @@ -68,7 +68,7 @@ export const LocalConfig: React.FC = ({ instanceUrl }) => { ); }} > - {isLoading ? "Saving..." : "Save"} + {isPending ? "Saving..." : "Save"} diff --git a/apps/dashboard/src/components/engine/contract-subscription/contract-subscriptions-table.tsx b/apps/dashboard/src/components/engine/contract-subscription/contract-subscriptions-table.tsx index 3bb03ad76..7200e9bab 100644 --- a/apps/dashboard/src/components/engine/contract-subscription/contract-subscriptions-table.tsx +++ b/apps/dashboard/src/components/engine/contract-subscription/contract-subscriptions-table.tsx @@ -19,7 +19,7 @@ import { type UseDisclosureReturn, useDisclosure, } from "@chakra-ui/react"; -import { useQuery } from "@tanstack/react-query"; +import { keepPreviousData, useQuery } from "@tanstack/react-query"; import { createColumnHelper } from "@tanstack/react-table"; import { ChainIcon } from "components/icons/ChainIcon"; import { TWTable } from "components/shared/TWTable"; @@ -254,7 +254,7 @@ const ChainLastBlockTimestamp = ({ const ethBlockQuery = useQuery({ queryKey: ["block_timestamp", chainId, Number(blockNumber)], // keep the previous data while fetching new data - keepPreviousData: true, + placeholderData: keepPreviousData, queryFn: async () => { const rpcRequest = getRpcClient({ client: thirdwebClient, diff --git a/apps/dashboard/src/components/engine/engine-instances-table.tsx b/apps/dashboard/src/components/engine/engine-instances-table.tsx index 64516b37a..01e602710 100644 --- a/apps/dashboard/src/components/engine/engine-instances-table.tsx +++ b/apps/dashboard/src/components/engine/engine-instances-table.tsx @@ -270,7 +270,7 @@ const EditModal = (props: { className="gap-2" disabled={!form.formState.isDirty} > - {editInstance.isLoading ? ( + {editInstance.isPending ? ( ) : ( @@ -363,7 +363,7 @@ function RemoveFromDashboardModalContent(props: { variant="destructive" className="gap-2" > - {removeFromDashboard.isLoading ? ( + {removeFromDashboard.isPending ? ( ) : ( @@ -493,7 +493,7 @@ function CancelSubscriptionModalContent(props: { disabled={!form.formState.isValid} className="gap-2" > - {removeCloudHosted.isLoading ? ( + {removeCloudHosted.isPending ? ( ) : ( diff --git a/apps/dashboard/src/components/engine/overview/backend-wallets-table.tsx b/apps/dashboard/src/components/engine/overview/backend-wallets-table.tsx index 5fcdd7e6e..0b63663d2 100644 --- a/apps/dashboard/src/components/engine/overview/backend-wallets-table.tsx +++ b/apps/dashboard/src/components/engine/overview/backend-wallets-table.tsx @@ -316,7 +316,7 @@ const ReceiveFundsModal = ({ // only run this if we have a backendWallet address enabled: !!backendWallet.address, // start out with empty string - initialData: "", + placeholderData: "", queryFn: async () => { return new Promise((resolve, reject) => { QRCode.toDataURL( diff --git a/apps/dashboard/src/components/engine/overview/transaction-timeline.tsx b/apps/dashboard/src/components/engine/overview/transaction-timeline.tsx index 3564513ab..3b5039f93 100644 --- a/apps/dashboard/src/components/engine/overview/transaction-timeline.tsx +++ b/apps/dashboard/src/components/engine/overview/transaction-timeline.tsx @@ -136,7 +136,6 @@ export const TransactionTimeline = ({ } active={} /> - {isFilled ? ( @@ -152,7 +151,6 @@ export const TransactionTimeline = ({ )} - ); diff --git a/apps/dashboard/src/components/ipfs-upload/button.tsx b/apps/dashboard/src/components/ipfs-upload/button.tsx index 114cf4660..3ad2791bc 100644 --- a/apps/dashboard/src/components/ipfs-upload/button.tsx +++ b/apps/dashboard/src/components/ipfs-upload/button.tsx @@ -33,7 +33,7 @@ export const IpfsUploadButton: ComponentWithChildren = ({ variant="solid" aria-label="Upload to IPFS" rightIcon={} - isLoading={storageUpload.isLoading} + isLoading={storageUpload.isPending} {...buttonProps} > {children} diff --git a/apps/dashboard/src/components/ipfs-upload/dropzone.tsx b/apps/dashboard/src/components/ipfs-upload/dropzone.tsx index 4da52daa7..38c45e955 100644 --- a/apps/dashboard/src/components/ipfs-upload/dropzone.tsx +++ b/apps/dashboard/src/components/ipfs-upload/dropzone.tsx @@ -310,7 +310,7 @@ const FileUpload: React.FC = ({ files, updateFiles }) => { e.stopPropagation(); updateFiles((prev) => prev.filter((f) => f !== file)); }} - isDisabled={storageUpload.isLoading} + isDisabled={storageUpload.isPending} /> )} @@ -361,7 +361,6 @@ const FileUpload: React.FC = ({ files, updateFiles }) => { ); })} - {showPagination && ( = ({ files, updateFiles }) => { )} - = ({ files, updateFiles }) => { {/* If user is uploading just one file, we allow them to choose if they want to upload without a folder */} {files.length === 1 && - !storageUpload.isLoading && + !storageUpload.isPending && ipfsHashes.length === 0 && ( = ({ files, updateFiles }) => { )} - {storageUpload.isLoading && ( + {storageUpload.isPending && ( = ({ files, updateFiles }) => { size={{ base: "xs", md: "lg" }} w="100%" borderRadius="full" - isIndeterminate={storageUpload.isLoading} + isIndeterminate={storageUpload.isPending} position="relative" />
= ({ files, updateFiles }) => { )} ) : ( @@ -107,7 +107,7 @@ const OnboardingLinkWallet: React.FC = ({ fontSize="md" variant="outline" onClick={onBack} - isDisabled={updateMutation.isLoading} + isDisabled={updateMutation.isPending} > Use another email diff --git a/apps/dashboard/src/components/pay/PayAnalytics/components/ExportToCSVButton.tsx b/apps/dashboard/src/components/pay/PayAnalytics/components/ExportToCSVButton.tsx index 306315a66..332ac8152 100644 --- a/apps/dashboard/src/components/pay/PayAnalytics/components/ExportToCSVButton.tsx +++ b/apps/dashboard/src/components/pay/PayAnalytics/components/ExportToCSVButton.tsx @@ -31,7 +31,7 @@ export function ExportToCSVButton(props: { exportMutation.mutate(); }} > - {exportMutation.isLoading ? ( + {exportMutation.isPending ? ( <> Downloading diff --git a/apps/dashboard/src/components/pay/PayAnalytics/components/PayCustomersTable.tsx b/apps/dashboard/src/components/pay/PayAnalytics/components/PayCustomersTable.tsx index acb0425c7..39d207526 100644 --- a/apps/dashboard/src/components/pay/PayAnalytics/components/PayCustomersTable.tsx +++ b/apps/dashboard/src/components/pay/PayAnalytics/components/PayCustomersTable.tsx @@ -48,11 +48,15 @@ function processQuery( return { isError: true }; } + if (!topCustomersQuery.data) { + return { isEmpty: true }; + } + let customers = topCustomersQuery.data.pages.flatMap( (x) => x.pageData.customers, ); - customers = customers.filter((x) => x.totalSpendUSDCents > 0); + customers = customers?.filter((x) => x.totalSpendUSDCents > 0); if (customers.length === 0) { return { isEmpty: true }; @@ -169,13 +173,11 @@ function RenderData(props: { query: ProcessedQuery; loadMore: () => void }) { )} - {props.query.isEmpty && (
No data available
)} - {props.query.data?.showLoadMore && (
- {/* Right */}
diff --git a/apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayCustomers.ts b/apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayCustomers.ts index 8823ccad9..a2e12e1a8 100644 --- a/apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayCustomers.ts +++ b/apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayCustomers.ts @@ -26,7 +26,7 @@ export function usePayCustomers(options: { return useInfiniteQuery({ queryKey: ["usePayCustomers", user?.address, options], - queryFn: async ({ pageParam = 0 }) => { + queryFn: async ({ pageParam }) => { const endpoint = options.type === "new-customers" ? "/stats/new-customers/v1" @@ -73,6 +73,7 @@ export function usePayCustomers(options: { }; }, enabled: !!user?.jwt, + initialPageParam: 0, getNextPageParam: (lastPage) => { return lastPage.nextPageIndex; }, diff --git a/apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayPurchases.ts b/apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayPurchases.ts index 9414fb55f..1bb135840 100644 --- a/apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayPurchases.ts +++ b/apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayPurchases.ts @@ -1,5 +1,5 @@ import { useLoggedInUser } from "@3rdweb-sdk/react/hooks/useLoggedInUser"; -import { useQuery } from "@tanstack/react-query"; +import { keepPreviousData, useQuery } from "@tanstack/react-query"; export type PayPurchasesData = { count: number; @@ -67,7 +67,8 @@ export function usePayPurchases(options: PayPurcaseOptions) { queryKey: ["usePayPurchases", user?.address, options], queryFn: async () => getPayPurchases(options), enabled: !!user?.jwt, - keepPreviousData: true, + // keep the previous data while fetching new data + placeholderData: keepPreviousData, }); } diff --git a/apps/dashboard/src/components/pay/PayConfig.tsx b/apps/dashboard/src/components/pay/PayConfig.tsx index 45a1f7670..c43679c60 100644 --- a/apps/dashboard/src/components/pay/PayConfig.tsx +++ b/apps/dashboard/src/components/pay/PayConfig.tsx @@ -152,11 +152,11 @@ export const PayConfig: React.FC = ({ apiKey }) => { diff --git a/apps/dashboard/src/components/settings/Account/AccountForm.tsx b/apps/dashboard/src/components/settings/Account/AccountForm.tsx index e337d8c7c..11dfa37a1 100644 --- a/apps/dashboard/src/components/settings/Account/AccountForm.tsx +++ b/apps/dashboard/src/components/settings/Account/AccountForm.tsx @@ -243,10 +243,10 @@ export const AccountForm: React.FC = ({ onClick={handleSubmit} colorScheme={buttonProps?.variant ? undefined : "blue"} isDisabled={ - updateMutation.isLoading || + updateMutation.isPending || (disableUnchanged && !form.formState.isDirty) } - isLoading={updateMutation.isLoading} + isLoading={updateMutation.isPending} > {buttonText} diff --git a/apps/dashboard/src/components/settings/Account/Billing/alerts/Alert.tsx b/apps/dashboard/src/components/settings/Account/Billing/alerts/Alert.tsx index 6225ad541..b7f128b94 100644 --- a/apps/dashboard/src/components/settings/Account/Billing/alerts/Alert.tsx +++ b/apps/dashboard/src/components/settings/Account/Billing/alerts/Alert.tsx @@ -48,7 +48,7 @@ export const BillingAlerts = () => { AccountStatus.InvalidPayment, AccountStatus.InvalidPaymentMethod, AccountStatus.PaymentVerification, - ].includes(account?.status as AccountStatus) + ].includes(account.state.data?.status as AccountStatus) ? 1000 : false, }); diff --git a/apps/dashboard/src/components/settings/Account/Billing/index.tsx b/apps/dashboard/src/components/settings/Account/Billing/index.tsx index 045c753dd..c32e56a3e 100644 --- a/apps/dashboard/src/components/settings/Account/Billing/index.tsx +++ b/apps/dashboard/src/components/settings/Account/Billing/index.tsx @@ -276,7 +276,7 @@ export const Billing: React.FC = ({ account }) => { validPayment={validPayment} paymentVerification={paymentVerification} invalidPayment={invalidPayment} - loading={paymentMethodSaving || updatePlanMutation.isLoading} + loading={paymentMethodSaving || updatePlanMutation.isPending} onSelect={handlePlanSelect} /> @@ -301,7 +301,7 @@ export const Billing: React.FC = ({ account }) => { oldPlanFeatures={PLANS[account.plan].features} onClose={handleDowngradeAlertClose} onConfirm={(feedback) => handleUpdatePlan(downgradePlan, feedback)} - loading={updatePlanMutation.isLoading} + loading={updatePlanMutation.isPending} /> )} diff --git a/apps/dashboard/src/components/settings/ApiKeys/Create/index.tsx b/apps/dashboard/src/components/settings/ApiKeys/Create/index.tsx index 0393d5a1b..020cbc654 100644 --- a/apps/dashboard/src/components/settings/ApiKeys/Create/index.tsx +++ b/apps/dashboard/src/components/settings/ApiKeys/Create/index.tsx @@ -214,7 +214,7 @@ function CreateAPIKeyForm(props: { return ( { handleAPICreation({ name: form.getValues("name"), @@ -338,10 +338,10 @@ function CreateAPIKeyForm(props: { diff --git a/apps/dashboard/src/components/smart-wallets/SponsorshipPolicies/index.tsx b/apps/dashboard/src/components/smart-wallets/SponsorshipPolicies/index.tsx index e78739dee..88856dc54 100644 --- a/apps/dashboard/src/components/smart-wallets/SponsorshipPolicies/index.tsx +++ b/apps/dashboard/src/components/smart-wallets/SponsorshipPolicies/index.tsx @@ -194,7 +194,6 @@ export const SponsorshipPolicies: React.FC = ({ - { // invalidate all queries to do with pinned files - return queryClient.invalidateQueries([PINNED_FILES_QUERY_KEY_ROOT]); + return queryClient.invalidateQueries({ + queryKey: [PINNED_FILES_QUERY_KEY_ROOT], + }); }, }); } @@ -154,10 +161,10 @@ const columns = [ ]; const UnpinButton: React.FC<{ cid: string }> = ({ cid }) => { - const { mutateAsync, isLoading } = useUnpinFileMutation(); + const { mutateAsync, isPending } = useUnpinFileMutation(); return ( diff --git a/apps/dashboard/src/contract-ui/tabs/manage/components/InstalledModulesTable.tsx b/apps/dashboard/src/contract-ui/tabs/manage/components/InstalledModulesTable.tsx index b1000955c..f53736c2b 100644 --- a/apps/dashboard/src/contract-ui/tabs/manage/components/InstalledModulesTable.tsx +++ b/apps/dashboard/src/contract-ui/tabs/manage/components/InstalledModulesTable.tsx @@ -223,7 +223,7 @@ function ModuleRow(props: { variant="outline" className="text-red-500 rounded-xl p-3" > - {uninstallMutation.isLoading ? ( + {uninstallMutation.isPending ? ( ) : ( @@ -267,7 +267,7 @@ function ModuleRow(props: { { Publisher { >