Skip to content

Wallet scene add 24h-pnl#1667

Merged
gemcoder21 merged 16 commits intomainfrom
wallet-pnl
Feb 16, 2026
Merged

Wallet scene add 24h-pnl#1667
gemcoder21 merged 16 commits intomainfrom
wallet-pnl

Conversation

@gemdev111
Copy link
Contributor

@gemdev111 gemdev111 commented Feb 2, 2026

  • Add daily profit/loss (P&L) display on wallet header showing amount change and
    percentage badge
    • Create centralized PriceChangeCalculator for percentage and amount
      calculations
    • Create TotalFiatValue model to track wallet value with P&L data
    • Update TotalValueRequest to calculate and return P&L from 24h price changes
    • Refactor and consolidate price change calculations across codebase using
      PriceChangeCalculator
    • Remove wrapper methods and inline calculations - all callers use
      PriceChangeCalculator directly
    • Clean up unused imports and fix access modifiers (private properties, removed
      Foundation/BigInt where unused)
    • Simplify TotalValueRequest with functional reduce pattern

images:
image
closes #1652

Add PriceChangeCalculator and TotalFiatValue types and centralize price-change logic. Replace ad-hoc percentage/amount calculations across charts, PnL, price impact and perpetual estimations with PriceChangeCalculator. Introduce TotalValueViewModel to present TotalFiatValue and refactor WalletHeaderViewModel, WalletHeaderView, and related header view models to support subtitle badge and color. Update store TotalValueRequest to compute aggregated total value and PnL, remove WalletFiatValue, and add corresponding tests and test helpers. Misc: adjust usages in Perpetuals, Chart views, PnLViewModel, and update unit tests to match the new types.
@gemdev111 gemdev111 self-assigned this Feb 2, 2026
@gemdev111 gemdev111 changed the title Wallet page pnl Wallet scene add 24h-pnl Feb 2, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @gemdev111, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the wallet's user interface by introducing a daily profit/loss (P&L) display directly in the header. It achieves this by centralizing all price change calculations into a new, dedicated utility and refactoring the underlying data models and requests to support this new P&L data. The changes improve consistency in financial calculations and provide users with immediate insights into their wallet's performance.

Highlights

  • Daily Profit/Loss (P&L) Display: Implemented a daily P&L display on the wallet header, showing both amount change and a percentage badge for a quick overview of performance.
  • Centralized Price Change Calculation: Introduced a new PriceChangeCalculator to centralize and standardize percentage and amount calculations related to price changes across the codebase.
  • New TotalFiatValue Model: Created a TotalFiatValue model to encapsulate and track the wallet's total value along with its associated P&L data (amount and percentage).
  • Updated TotalValueRequest: Refactored TotalValueRequest to calculate and return P&L based on 24-hour price changes, leveraging the new PriceChangeCalculator.
  • Code Refactoring and Consolidation: Consolidated existing price change calculations by migrating them to use the new PriceChangeCalculator, removing redundant wrapper methods and inline calculations.
  • Code Cleanup: Performed general code cleanup, including removing unused imports (e.g., Foundation, BigInt) and adjusting access modifiers for improved code quality.
  • Wallet Header Enhancements: The WalletHeaderView now supports displaying the P&L badge and dynamically adjusts subtitle colors based on P&L performance.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a 24-hour profit and loss (P&L) display in the wallet header, which is a great enhancement for users. The implementation includes a new centralized PriceChangeCalculator and a TotalFiatValue model, which are positive steps towards better code structure and reusability. The refactoring across the codebase to use these new components is well-executed.

However, I've found a critical issue in the P&L calculation logic within PriceChangeCalculator for the specific edge case where an asset's value drops by 100%. This leads to incorrect P&L reporting. The corresponding test case also seems to be flawed, reinforcing this incorrect behavior. Addressing this is crucial for the financial correctness of the feature.

The rest of the changes look good and align with the goals of the pull request.

return from == 0 ? 0 : (to - from) / from * 100
case .amount(let percentage, let value):
let denominator = 100 + percentage
return denominator == 0 ? 0 : value * percentage / denominator
Copy link
Contributor

Choose a reason for hiding this comment

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

critical

The calculation for the .amount case is incorrect when percentage is exactly -100. In this scenario, the denominator becomes zero, and the function currently returns 0, which is incorrect.

  • A -100% change implies the final value is 0. The profit and loss (P&L) amount should be the negative of the initial value (e.g., if value goes from $100 to $0, P&L is -$100, not $0).
  • The formula P&L = V_final * percentage / (100 + percentage) has a singularity at percentage = -100, where V_final must be 0, and the initial value cannot be determined.

The current implementation silently returns an incorrect P&L of 0, leading to flawed portfolio P&L calculations. This might require a data model change to provide the initial value or price change amount directly. The calculator should not return a misleading 0 for this case.

#expect(PriceChangeCalculator.calculate(.amount(percentage: 10, value: 110)) == 10)
#expect(PriceChangeCalculator.calculate(.amount(percentage: -10, value: 90)) == -10)
#expect(PriceChangeCalculator.calculate(.amount(percentage: 0, value: 100)) == 0)
#expect(PriceChangeCalculator.calculate(.amount(percentage: -100, value: 100)) == 0)
Copy link
Contributor

Choose a reason for hiding this comment

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

high

This test case for a -100% change is flawed and validates incorrect behavior:

  1. Logically impossible scenario: A -100% change in value means the final value must be 0. The test provides a final value of 100, which is a contradiction.
  2. Incorrect expectation: The expected P&L of 0 is wrong. For a -100% change, the P&L is the negative of the initial value.

This test should be corrected to reflect a valid scenario and a correct expectation. The current test is misleading and hides a critical bug in the P&L calculation.

gemdev111 and others added 3 commits February 3, 2026 14:16
Update test fixtures to use an Ethereum asset instead of Bitcoin and adjust prices accordingly (50000 -> 3000) in TotalValueRequestTests. Remove a redundant/invalid expectation for a -100% price change in PriceChangeCalculatorTests. These changes keep tests consistent with expected asset/pricing assumptions.
The tests were failing because priceStore.updatePrice() requires
a fiat rate to be present in the database for the given currency.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
subtitle,
isEnabled: $isPrivacyEnabled
)
.font(.system(size: 16, weight: .medium))
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe something from our fonts fits?

var assetImage: AssetImage? { get }
var title: String { get }
var subtitle: String? { get }
var subtitleBadge: String? { get }
Copy link
Contributor

Choose a reason for hiding this comment

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

can we use TextValue?

import PrimitivesTestKit
import Primitives

struct TotalValueRequestTests {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we assert the exact expected values here?

Use price=1100 to get clean divisible numbers:
- value = 3300 (3 * 1100)
- pnlAmount = 300 (3300 * 10 / 110)
- pnlPercentage = 10

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@gemdev111 gemdev111 requested a review from DRadmir February 3, 2026 16:27
Replace separate subtitle badge with an inline percentage and optional arrow image. HeaderViewModel protocol now exposes subtitleImage instead of subtitleBadge. WalletHeaderView concatenates amount and percentage into a single subtitle and shows a small up/down arrow Image (styled with subtitle color) instead of a capsule badge; spacing adjusted. WalletHeaderViewModel builds the combined subtitle and returns an arrow image based on pnl sign. Tests updated to expect the new subtitle format, and system image names for the arrows were added.
@gemcoder21 gemcoder21 merged commit dba7954 into main Feb 16, 2026
1 check passed
@gemcoder21 gemcoder21 deleted the wallet-pnl branch February 16, 2026 18:36
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.

Add Balance change (amount + percent change)

3 participants