Skip to content

refactor: enhance wallet balance fetching to include raw balances#392

Merged
onahprosper merged 2 commits intomainfrom
fix-balance-conversion-error-during-migration
Feb 27, 2026
Merged

refactor: enhance wallet balance fetching to include raw balances#392
onahprosper merged 2 commits intomainfrom
fix-balance-conversion-error-during-migration

Conversation

@Dprof-in-tech
Copy link
Copy Markdown
Collaborator

@Dprof-in-tech Dprof-in-tech commented Feb 27, 2026

Description

This pull request enhances the wallet transfer approval flow by improving how token balances are handled and transferred. The main improvement is the consistent use of raw token amounts (as bigint) throughout the balance fetching and transfer process, ensuring accuracy for all token values, including very small amounts. This eliminates the need for parsing and conversion at the transfer step, reducing potential errors and simplifying the code.

Wallet Balance Handling Improvements:

  • The fetchWalletBalance utility now returns both human-readable balances and raw token balances (as bigint) in a new rawBalances field, ensuring precise value handling for all tokens. [1] [2] [3] [4]
  • The wallet transfer approval modal (WalletTransferApprovalModal.tsx) stores and utilizes these raw balances in a new state variable allChainRawBalances, keeping them in sync with the existing human-readable balances. [1] [2] [3] [4]

Token Transfer Logic Updates:

  • The transfer batching logic now uses the raw token amounts directly (token.rawAmount) when encoding transfer transactions, removing the need for parseUnits and preventing rounding or precision issues.

Code Clean-up:

  • Removed the unused parseUnits import from viem in WalletTransferApprovalModal.tsx as it is no longer necessary.

React Dependency Updates:

  • Updated React useMemo dependencies to include allChainRawBalances, ensuring the UI stays in sync with raw balance changes.

  • Updated fetchWalletBalance function to return rawBalances as bigint for improved precision.

  • Modified WalletTransferApprovalModal to handle and display raw balances alongside regular balances.

  • Ensured compatibility with existing balance fetching logic while enhancing data structure for better usability.

References

Screenshot 2026-02-27 at 11 31 26 am

Testing

  • This change adds test coverage for new/changed/fixed functionality

Checklist

  • I have added documentation and tests for new/changed functionality in this PR
  • All active GitHub checks for tests, formatting, and security are passing
  • The correct base branch is being used, if not main

By submitting a PR, I agree to Paycrest's Contributor Code of Conduct and Contribution Guide.

Summary by CodeRabbit

  • Improvements
    • Added per-chain raw token balances (high-precision amounts) throughout the wallet UI and transfer flows for more accurate transfer calculations.
    • Wallet balance fetch now returns raw balance data alongside numeric totals, improving precision and consistency for batch transfers and value displays.
    • USD value calculations preserved while relying on the new raw amounts for transfer encoding.

* Updated fetchWalletBalance function to return rawBalances as bigint for improved precision.
* Modified WalletTransferApprovalModal to handle and display raw balances alongside regular balances.
* Ensured compatibility with existing balance fetching logic while enhancing data structure for better usability.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 27, 2026

📝 Walkthrough

Walkthrough

Added chain-level raw bigint balance tracking (balancesInWei / allChainRawBalances) and threaded those raw amounts into token objects as rawAmount. fetchWalletBalance return shape changed to include balancesInWei; WalletTransferApprovalModal now uses token.rawAmount for transfer encoding and removed parseUnits usage.

Changes

Cohort / File(s) Summary
Balance Fetching
app/utils.ts
fetchWalletBalance return shape extended to include balancesInWei: Record<string, bigint>; native and ERC-20 balances populated as BigInt (wei) across success and error paths.
Transfer Approval UI / Encoding
app/components/WalletTransferApprovalModal.tsx
Added allChainRawBalances state, propagated rawAmount into token objects, updated USD/value computations to use existing rates, replaced parseUnits/amount-in-wei conversion by using token.rawAmount for batch transfer encoding, removed parseUnits import.

Sequence Diagram(s)

(Skipped — changes are focused on data plumbing and encoding within two components, not a new multi-actor control flow requiring visualization.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • chibie
  • 5ran6

Poem

🐰 I hop with bigint joy today,
Wei in paws, no parse to fray,
Raw amounts snug in every token,
Clean transfers — never broken. ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately summarizes the main change: enhancing wallet balance fetching to include raw balances (bigint) for improved precision during transfers.
Description check ✅ Passed The description comprehensively covers purpose, implementation details, and impacts, but lacks concrete testing information and documentation confirmation despite checklist items being unchecked.
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 docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-balance-conversion-error-during-migration

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.

Copy link
Copy Markdown
Contributor

@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 (1)
app/components/WalletTransferApprovalModal.tsx (1)

79-104: Consider concurrent chain balance fetches to reduce modal load latency.

This loop is currently serial; moving to a concurrent best-effort fetch pattern will make balance hydration much faster while still tolerating per-chain failures.

♻️ Suggested refactor
-            // Fetch balances for each supported network
-            for (const network of networks) {
-                try {
-                    const publicClient = createPublicClient({
-                        chain: network.chain,
-                        transport: getTransportForChain(network.chain),
-                    });
-
-                    const result = await fetchWalletBalance(
-                        publicClient,
-                        oldAddress
-                    );
-
-                    // Only include chains with non-zero balances
-                    const hasBalance = Object.values(result.balances).some(b => b > 0);
-                    if (hasBalance) {
-                        balancesByChain[network.chain.name] = result.balances;
-                        rawByChain[network.chain.name] = result.rawBalances;
-                    }
-                } catch (error) {
-                    console.error(`Error fetching balances for ${network.chain.name}:`, error);
-                }
-            }
+            const settled = await Promise.allSettled(
+                networks.map(async (network) => {
+                    const publicClient = createPublicClient({
+                        chain: network.chain,
+                        transport: getTransportForChain(network.chain),
+                    });
+                    const result = await fetchWalletBalance(publicClient, oldAddress);
+                    return { chainName: network.chain.name, result };
+                })
+            );
+
+            for (const item of settled) {
+                if (item.status !== "fulfilled") continue;
+                const { chainName, result } = item.value;
+                const hasBalance = Object.values(result.balances).some((b) => b > 0);
+                if (!hasBalance) continue;
+                balancesByChain[chainName] = result.balances;
+                rawByChain[chainName] = result.rawBalances;
+            }

Based on learnings: In TSX files that perform parallel network fetches, use a graceful-degradation approach that keeps fulfilled results and avoids failing the whole flow on individual rejections.

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

In `@app/components/WalletTransferApprovalModal.tsx` around lines 79 - 104, The
serial for-loop in WalletTransferApprovalModal that calls createPublicClient and
fetchWalletBalance for each network should be made concurrent: map networks to
promises that perform the per-chain fetch (using
createPublicClient/getTransportForChain and fetchWalletBalance), then await
Promise.allSettled on that array, iterate the settled results and for each
fulfilled entry add to balancesByChain and rawByChain (using network.chain.name
as the key), and ignore/log rejected entries; finally call setAllChainBalances,
setAllChainRawBalances, and setIsFetchingBalances(false). This keeps best-effort
behavior per-chain while significantly reducing latency.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/components/WalletTransferApprovalModal.tsx`:
- Around line 79-104: The serial for-loop in WalletTransferApprovalModal that
calls createPublicClient and fetchWalletBalance for each network should be made
concurrent: map networks to promises that perform the per-chain fetch (using
createPublicClient/getTransportForChain and fetchWalletBalance), then await
Promise.allSettled on that array, iterate the settled results and for each
fulfilled entry add to balancesByChain and rawByChain (using network.chain.name
as the key), and ignore/log rejected entries; finally call setAllChainBalances,
setAllChainRawBalances, and setIsFetchingBalances(false). This keeps best-effort
behavior per-chain while significantly reducing latency.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 52f5676 and 23ba683.

📒 Files selected for processing (2)
  • app/components/WalletTransferApprovalModal.tsx
  • app/utils.ts

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Free Tier Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment thread app/utils.ts Outdated
onahprosper
onahprosper previously approved these changes Feb 27, 2026
…ved precision

* Modified fetchWalletBalance function to replace rawBalances with balancesInWei, enhancing the accuracy of balance data.
* Updated WalletTransferApprovalModal to utilize balancesInWei for consistency in balance handling.
* Ensured compatibility with existing logic while improving data structure for better usability.
Copy link
Copy Markdown
Contributor

@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 (1)
app/utils.ts (1)

591-608: Return type of fetchBalanceForNetwork is now out of sync with fetchWalletBalance.

This wrapper function's return type still declares Promise<{ total: number; balances: Record<string, number> }>, but it returns the result of fetchWalletBalance which now includes balancesInWei. While this won't break existing callers, the type inconsistency may cause confusion.

♻️ Suggestion: Update return type for consistency
 export async function fetchBalanceForNetwork(
   network: { chain: any },
   walletAddress: string,
-): Promise<{ total: number; balances: Record<string, number> }> {
+): Promise<{ total: number; balances: Record<string, number>; balancesInWei: Record<string, bigint> }> {
   const { createPublicClient, http } = await import("viem");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/utils.ts` around lines 591 - 608, The declared return type of
fetchBalanceForNetwork is outdated: it currently promises { total, balances }
but actually returns fetchWalletBalance(...) which now includes balancesInWei;
update fetchBalanceForNetwork's signature to match fetchWalletBalance by adding
the balancesInWei field (and exact type used by fetchWalletBalance) so the
function signature for fetchBalanceForNetwork aligns with fetchWalletBalance's
returned shape.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/utils.ts`:
- Around line 591-608: The declared return type of fetchBalanceForNetwork is
outdated: it currently promises { total, balances } but actually returns
fetchWalletBalance(...) which now includes balancesInWei; update
fetchBalanceForNetwork's signature to match fetchWalletBalance by adding the
balancesInWei field (and exact type used by fetchWalletBalance) so the function
signature for fetchBalanceForNetwork aligns with fetchWalletBalance's returned
shape.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 23ba683 and 22cf052.

📒 Files selected for processing (2)
  • app/components/WalletTransferApprovalModal.tsx
  • app/utils.ts

@onahprosper onahprosper merged commit ca4dfaa into main Feb 27, 2026
2 checks passed
@onahprosper onahprosper deleted the fix-balance-conversion-error-during-migration branch February 27, 2026 10:55
@coderabbitai coderabbitai bot mentioned this pull request Mar 3, 2026
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants