Skip to content

feat: unify balance query keys and fix useRefreshBalances#602

Open
Emilvooo wants to merge 1 commit intovechain:mainfrom
Emilvooo:feat/unify-balance-query-keys
Open

feat: unify balance query keys and fix useRefreshBalances#602
Emilvooo wants to merge 1 commit intovechain:mainfrom
Emilvooo:feat/unify-balance-query-keys

Conversation

@Emilvooo
Copy link
Contributor

@Emilvooo Emilvooo commented Mar 10, 2026

Summary

  • Unify all balance/price query keys under a consistent ['VECHAIN_KIT', 'BALANCE', ...] prefix
  • Fix useRefreshBalances not invalidating B3TR, VOT3, and ERC-20 balances
  • Export VECHAIN_KIT_QUERY_KEYS constant for stable cache invalidation

Problem

Balance query keys used three different root prefixes (VECHAIN_KIT_BALANCE, VEBETTERDAO_BALANCE, ['VECHAIN_KIT', 'BALANCE', ...]). Because of this, useRefreshBalances only invalidated the first prefix, leaving B3TR, VOT3, and ERC-20 balances stale after transactions.

Solution

All keys now share ['VECHAIN_KIT', 'BALANCE'] as root, defined in a single VECHAIN_KIT_QUERY_KEYS constant. This allows invalidating all balances at once:

queryClient.invalidateQueries({ queryKey: VECHAIN_KIT_QUERY_KEYS.balance.all });

useRefreshBalances uses this prefix to correctly invalidate all balance types.

Breaking changes

Consumers hardcoding query key strings (e.g. ['VECHAIN_KIT_BALANCE', address]) need to switch to the exported getXxxQueryKey functions or VECHAIN_KIT_QUERY_KEYS. Consumers already using the exported functions are unaffected.

Summary by CodeRabbit

  • Refactor
    • Consolidated query key definitions for balance and price operations into a centralized system.
    • Updated balance and price query hooks to use the unified key structure.
    • Simplified cache invalidation logic for balance refresh operations.

@github-actions
Copy link

👋 Thanks for your contribution!

Since this PR comes from a forked repository, the lint and build will only run for internal PRs for security reasons.
Please ensure that your PR is coming from a meaningful branch name. Eg. feature/my-feature not main

      **Next steps:**
      1. A maintainer will review your code
      2. If approved, they'll add the `safe-to-build` label to trigger build and test
      3. **After each new commit**, the maintainer will need to remove and re-add the label for security

Thank you for your patience! 🙏

@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

This PR introduces centralized query key management by creating a VECHAIN_KIT_QUERY_KEYS constant object with structured query key factories for balance and price queries. The constant is exported from constants and hooks indices, and all hardcoded query key arrays across wallet and account balance hooks are replaced with delegated calls to this centralized management system.

Changes

Cohort / File(s) Summary
Constants Setup
packages/vechain-kit/src/constants/queryKeys.ts, packages/vechain-kit/src/constants/index.ts
Introduces new queryKeys.ts file exporting VECHAIN_KIT_QUERY_KEYS constant with balance (all, native, b3tr, vot3, erc20, customToken) and price (all, token) query key factories; added re-export from constants index.
Wallet Balance Hooks
packages/vechain-kit/src/hooks/api/wallet/useGetB3trBalance.ts, packages/vechain-kit/src/hooks/api/wallet/useGetVot3Balance.ts, packages/vechain-kit/src/hooks/api/wallet/useGetErc20Balance.ts, packages/vechain-kit/src/hooks/api/wallet/useGetCustomTokenBalances.ts
Replaces hardcoded query key arrays with centralized VECHAIN_KIT_QUERY_KEYS.balance.* accessors; imports new constant and updates key generation logic in each balance query function.
Token Price Hook
packages/vechain-kit/src/hooks/api/wallet/useGetTokenUsdPrice.ts
Replaces hardcoded price query key with VECHAIN_KIT_QUERY_KEYS.price.token(token) centralized key generator; adds import of new query keys constant.
Account Balance Hook
packages/vechain-kit/src/hooks/thor/accounts/useAccountBalance.ts
Updates getAccountBalanceQueryKey to use VECHAIN_KIT_QUERY_KEYS.balance.native(address) instead of hardcoded array; imports centralized query keys constant.
Balance Refresh Hook
packages/vechain-kit/src/hooks/api/wallet/useRefreshBalances.ts
Refactors to use grouped query keys (VECHAIN_KIT_QUERY_KEYS.balance.all and VECHAIN_KIT_QUERY_KEYS.price.all) instead of per-address invalidation; removes useWallet dependency and replaces per-key string literals with centralized constants.
Module Exports
packages/vechain-kit/src/hooks/index.ts
Adds public export of VECHAIN_KIT_QUERY_KEYS from constants module for external consumption.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

Suggested reviewers

  • Agilulfo1820

Poem

🐰 Hop, hop, the query keys now align,
No more scattered strings in code of mine!
Centralized, tidy, a rabbit's delight,
Each balance and price now structured just right! 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main objectives: unifying balance query keys under a consistent structure and fixing the useRefreshBalances hook to properly invalidate all balance types.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Agilulfo1820 Agilulfo1820 added safe-to-deploy Label to approve external PRs to preview environment safe-to-build labels Mar 10, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
packages/vechain-kit/src/hooks/api/wallet/useRefreshBalances.ts (1)

8-14: Avoid global cache fan-out for account-scoped refreshes.

refresh() is triggered from single-account flows like useTransferVET, useTransferERC20, and the account modal refresh button, but invalidating balance.all/price.all now refetches every cached balance and price query for every address/token in the session. That fixes the stale-key gap, but it also turns one wallet action into a full cache sweep.

Consider introducing an address-scoped balance prefix in VECHAIN_KIT_QUERY_KEYS and letting refresh target the affected account, with a global fallback only when you truly want a full refresh.

♻️ Suggested direction
-export const useRefreshBalances = () => {
+export const useRefreshBalances = (address?: string) => {
     const queryClient = useQueryClient();

     const refresh = async () => {
         await Promise.all([
             queryClient.invalidateQueries({
-                queryKey: VECHAIN_KIT_QUERY_KEYS.balance.all,
+                queryKey: address
+                    ? VECHAIN_KIT_QUERY_KEYS.balance.byAddress(address)
+                    : VECHAIN_KIT_QUERY_KEYS.balance.all,
             }),
             queryClient.invalidateQueries({
                 queryKey: VECHAIN_KIT_QUERY_KEYS.price.all,
             }),
         ]);

Add a matching balance.byAddress(address) prefix in packages/vechain-kit/src/constants/queryKeys.ts, then compose the per-token balance keys under it.

packages/vechain-kit/src/hooks/api/wallet/useGetCustomTokenBalances.ts (1)

23-50: Consider adding enabled condition to prevent unnecessary query execution.

The queries will execute and throw errors when address is undefined. Adding an enabled condition would prevent unnecessary error handling and align with the coding guidelines pattern.

♻️ Suggested improvement
     return useQueries({
         queries: customTokens.map((token) => ({
             queryKey: getCustomTokenBalanceQueryKey(token.address, address),
+            enabled: !!token.address && !!address && !!network.nodeUrl,
             queryFn: async () => {

As per coding guidelines: "Always conditionally enable queries using the enabled property to prevent unnecessary contract calls, checking for all required parameters"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vechain-kit/src/hooks/api/wallet/useGetCustomTokenBalances.ts`
around lines 23 - 50, The queries in useGetCustomTokenBalances are running even
when required params are missing; update the useQueries call (the
customTokens.map block that builds each query with getCustomTokenBalanceQueryKey
and queryFn calling getErc20Balance/formatTokenBalance) to include an enabled
property that checks all prerequisites (e.g., enabled: !!address &&
!!token.address && !!network?.nodeUrl) so the query only executes when address,
token.address and network.nodeUrl are present.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/vechain-kit/src/hooks/api/wallet/useGetCustomTokenBalances.ts`:
- Around line 23-50: The queries in useGetCustomTokenBalances are running even
when required params are missing; update the useQueries call (the
customTokens.map block that builds each query with getCustomTokenBalanceQueryKey
and queryFn calling getErc20Balance/formatTokenBalance) to include an enabled
property that checks all prerequisites (e.g., enabled: !!address &&
!!token.address && !!network?.nodeUrl) so the query only executes when address,
token.address and network.nodeUrl are present.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 61aa3d34-b767-46e1-8b37-f48ea1b358e1

📥 Commits

Reviewing files that changed from the base of the PR and between 40d9973 and c5ee070.

📒 Files selected for processing (10)
  • packages/vechain-kit/src/constants/index.ts
  • packages/vechain-kit/src/constants/queryKeys.ts
  • packages/vechain-kit/src/hooks/api/wallet/useGetB3trBalance.ts
  • packages/vechain-kit/src/hooks/api/wallet/useGetCustomTokenBalances.ts
  • packages/vechain-kit/src/hooks/api/wallet/useGetErc20Balance.ts
  • packages/vechain-kit/src/hooks/api/wallet/useGetTokenUsdPrice.ts
  • packages/vechain-kit/src/hooks/api/wallet/useGetVot3Balance.ts
  • packages/vechain-kit/src/hooks/api/wallet/useRefreshBalances.ts
  • packages/vechain-kit/src/hooks/index.ts
  • packages/vechain-kit/src/hooks/thor/accounts/useAccountBalance.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe-to-build safe-to-deploy Label to approve external PRs to preview environment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants