Skip to content

[LWM] feat(pay-card): add a Balance screen to the devtool - #21448

Draft
philipptpunkt wants to merge 1 commit into
fix/pay-card-schema-failure-detailfrom
feat/pay-card-devtools-balance
Draft

[LWM] feat(pay-card): add a Balance screen to the devtool#21448
philipptpunkt wants to merge 1 commit into
fix/pay-card-schema-failure-detailfrom
feat/pay-card-devtools-balance

Conversation

@philipptpunkt

@philipptpunkt philipptpunkt commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Stack (managed by stac-man)

The linked-wallet total has no UI that shows the number itself, so a wrong
total cannot be told apart from a wrong formatter. The devtool shows what the
calculation returned.

  • Opening the screen requests the wallets: the queries are skipped until then,
    so the tool does not fetch a cardholder's wallets to render a list of flags.
  • The total is rendered raw, in the counter-value currency's smallest unit.
    Formatting it would hide the unit bug this screen exists to catch.
  • A partial total says so. A wallet the rates could not price is left out of the
    sum rather than counted as zero, which otherwise reads as a complete total.
  • Pricing needs the app's rates and currency settings, so the host passes its
    resolver in, the same way the card visual gets one.

Copilot AI lite review requested due to automatic review settings September 2, 2026 12:49
@live-github-bot live-github-bot Bot added mobile Has changes in LLM devtools Has changes in the DevTools packages labels Sep 2, 2026
@live-github-bot live-github-bot Bot changed the title feat(pay-card): add a Balance screen to the devtool [LWM] feat(pay-card): add a Balance screen to the devtool Sep 2, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The bindings currently surface a misleading total: 0/no-error state when resolveCounterValue is absent, contradicting the stated “avoid wrong zero” intent and should be made explicit (e.g., error/partial state).

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds a new “Balance” view to the Pay Card devtool (mobile-first) to display the raw linked-wallet total returned by the balance calculation (unformatted), along with partial-total/error states, and wires host-side countervalue resolution into the devtool bindings.

Changes:

  • Introduces a native Balance screen in @devtools/pay-card, plus navigation from the Pay Card devtool entry list.
  • Extends the devtool props contract and bindings to expose linked-wallet totals via useCardLinkedWallets, lazily fetched when the screen opens.
  • Wires the mobile host to provide a resolveCounterValue implementation (and adjusts the DevTools integration test to account for async settling).
File summaries
File Description
pnpm-lock.yaml Adds workspace links for new devtool/bindings dependencies (@features/flow-pay-card-wallets, @shared/api-services).
devtools/pay-card/src/usePayCardViewModel.test.ts Updates test props builder to include new balance props contract.
devtools/pay-card/src/usePayCardViewModel.native.test.ts Updates native test props builder to include new balance props contract.
devtools/pay-card/src/types.ts Adds PayCardBalanceProps and extends PayCardToolProps with balance.
devtools/pay-card/src/pay-card/PayCard.web.test.tsx Updates web test props to include balance (even though UI remains web-noop).
devtools/pay-card/src/pay-card/PayCard.native.tsx Adds screen switching and entry point for the new Balance screen; calls balance.load() on open.
devtools/pay-card/src/pay-card/PayCard.native.test.tsx Adds tests covering load-on-open, refresh behavior, and partial-total messaging.
devtools/pay-card/src/components/Balance/Balance.web.tsx Adds web stub for Balance screen (native-only behavior for now).
devtools/pay-card/src/components/Balance/Balance.native.tsx Implements native Balance UI with total, linked wallet count, refresh, partial/error states.
devtools/bindings/src/usePayCardToolProps.ts Wires useCardLinkedWallets into bindings and exposes new balance props with lazy fetching.
devtools/bindings/src/usePayCardToolProps.test.tsx Adds cardApi reducer+middleware to the test store to support Card RTK Query usage.
devtools/bindings/package.json Adds @features/flow-pay-card-wallets dependency and @shared/api-services devDependency for tests.
apps/ledger-live-mobile/src/mvvm/features/DevTools/screens/DevToolsScreen/useDevToolsScreenViewModel.ts Passes host resolveCounterValue into usePayCardToolProps for mobile.
apps/ledger-live-mobile/src/mvvm/features/DevTools/integrations/DevToolsScreen.integration.test.tsx Uses the last DevTools render call to avoid flakiness from async query settling.
.changeset/pay-card-devtools-balance.md Declares version bumps for devtool packages and the mobile app.
Review details

Files not reviewed (1)

  • pnpm-lock.yaml: Generated file
  • Files reviewed: 14/15 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +165 to +176
const balance = useMemo(
() => ({
total: linkedWallets.total,
isPartialTotal: linkedWallets.isPartialTotal,
walletCount: linkedWallets.wallets.length,
isFetching: linkedWallets.isFetching,
error: linkedWallets.isError ? "The wallet endpoints answered with an error." : undefined,
load: loadWallets,
refresh: refreshWallets,
}),
[linkedWallets, loadWallets, refreshWallets],
);
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Web Tools Build Status

Build Status Deployment
Web Tools Build ✅ Deployed https://web-tools-h8se0frhx-ledger-hq-prd.vercel.app

@live-github-bot

live-github-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Mobile Bundle Checks

Comparing de8484a against a25a6c0.

⚠️ main.ios.jsbundle bundle size significantly increased: 62.5mb -> 62.9mb. Please check if this is expected.
⚠️ main.android.jsbundle bundle size significantly increased: 62.5mb -> 62.9mb. Please check if this is expected.

Desktop Bundle Checks

Comparing de8484a against ea5e753.

✅ Previous issues have all been fixed.

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Rsdoctor Bundle Diff Analysis

Found 7 projects in monorepo, 7 projects with changes.

📊 Quick Summary
Project Total Size Gzip Size Change Gzip Change
desktop-main 2.5 MB - - -
desktop-preloader 7.1 KB - - -
desktop-renderer 82.4 MB - - -
desktop-webviewDappPreloader 36.9 KB - - -
desktop-webviewPreloader 200.0 B - - -
desktop-workers 36.8 KB - - -
mobile 129.8 MB - - -
📋 Detailed Reports (Click to expand)

📁 desktop-main

Path: rsdoctor/desktop-main/rsdoctor-data.json

⚠️ No baseline data found - Unable to perform comparison analysis

Metric Current Baseline Change
📊 Total Size 2.5 MB - -
🗜️ Gzip Size - - -
📄 JavaScript 2.4 MB - -
🎨 CSS 0 B - -
🌐 HTML 0 B - -
📁 Other Assets 135.3 KB - -

📁 desktop-preloader

Path: rsdoctor/desktop-preloader/rsdoctor-data.json

⚠️ No baseline data found - Unable to perform comparison analysis

Metric Current Baseline Change
📊 Total Size 7.1 KB - -
🗜️ Gzip Size - - -
📄 JavaScript 5.3 KB - -
🎨 CSS 0 B - -
🌐 HTML 0 B - -
📁 Other Assets 1.8 KB - -

📁 desktop-renderer

Path: rsdoctor/desktop-renderer/rsdoctor-data.json

⚠️ No baseline data found - Unable to perform comparison analysis

Metric Current Baseline Change
📊 Total Size 82.4 MB - -
🗜️ Gzip Size - - -
📄 JavaScript 30.6 MB - -
🎨 CSS 188.4 KB - -
🌐 HTML 1.8 KB - -
📁 Other Assets 51.7 MB - -

📁 desktop-webviewDappPreloader

Path: rsdoctor/desktop-webviewDappPreloader/rsdoctor-data.json

⚠️ No baseline data found - Unable to perform comparison analysis

Metric Current Baseline Change
📊 Total Size 36.9 KB - -
🗜️ Gzip Size - - -
📄 JavaScript 36.9 KB - -
🎨 CSS 0 B - -
🌐 HTML 0 B - -
📁 Other Assets 0 B - -

📁 desktop-webviewPreloader

Path: rsdoctor/desktop-webviewPreloader/rsdoctor-data.json

⚠️ No baseline data found - Unable to perform comparison analysis

Metric Current Baseline Change
📊 Total Size 200.0 B - -
🗜️ Gzip Size - - -
📄 JavaScript 200.0 B - -
🎨 CSS 0 B - -
🌐 HTML 0 B - -
📁 Other Assets 0 B - -

📁 desktop-workers

Path: rsdoctor/desktop-workers/rsdoctor-data.json

⚠️ No baseline data found - Unable to perform comparison analysis

Metric Current Baseline Change
📊 Total Size 36.8 KB - -
🗜️ Gzip Size - - -
📄 JavaScript 36.8 KB - -
🎨 CSS 0 B - -
🌐 HTML 0 B - -
📁 Other Assets 0 B - -

📁 mobile

Path: rsdoctor/mobile/rsdoctor-data.json

⚠️ No baseline data found - Unable to perform comparison analysis

Metric Current Baseline Change
📊 Total Size 129.8 MB - -
🗜️ Gzip Size - - -
📄 JavaScript 114.4 MB - -
🎨 CSS 0 B - -
🌐 HTML 0 B - -
📁 Other Assets 15.5 MB - -

Generated by Rsdoctor GitHub Action

Copilot AI review requested due to automatic review settings September 2, 2026 13:01
@philipptpunkt
philipptpunkt force-pushed the feat/pay-card-devtools-balance branch from 110a583 to ec60bce Compare September 2, 2026 13:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The change is well-scoped, preserves lazy-fetch behavior, updates consumers/tests coherently, and includes an appropriate changeset.

Review details

Files not reviewed (1)

  • pnpm-lock.yaml: Generated file
  • Files reviewed: 14/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The Balance screen currently displays misleading “null” explanations that don’t match the actual states produced by the underlying join/pricing logic.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Files not reviewed (1)

  • pnpm-lock.yaml: Generated file
  • Files reviewed: 14/15 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment on lines +32 to +49
function Wallet({ wallet }: { readonly wallet: PayCardBalanceWallet }) {
return (
<Box lx={BLOCK_LX}>
<Text typography="body2">{`${wallet.priority}. ${wallet.currency} / ${wallet.network}`}</Text>
<Field label="balance" value={wallet.balance ?? "null — no internal wallet matched"} />
<Field
label="counterValue"
value={
wallet.counterValue === null
? "null — not priced, left out of the total"
: String(wallet.counterValue)
}
/>
<Field label="id" value={wallet.id} />
<Field label="address" value={wallet.address} />
</Box>
);
}
Comment on lines +62 to +65
/** `null` when no internal wallet matched this link. */
readonly balance: string | null;
/** `null` when the balance could not be priced. Those are left out of the total. */
readonly counterValue: number | null;
@philipptpunkt
philipptpunkt force-pushed the fix/pay-card-schema-failure-detail branch from bc54a09 to 7b9c907 Compare September 2, 2026 14:12
Copilot AI review requested due to automatic review settings September 2, 2026 14:12
@philipptpunkt
philipptpunkt force-pushed the feat/pay-card-devtools-balance branch from 95b1001 to 218ab25 Compare September 2, 2026 14:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The Balance screen can display a misleading 0 total before wallets are actually loaded/priced because total is always populated from a defaulted calculation even when queries are skipped.

Review details

Files not reviewed (1)

  • pnpm-lock.yaml: Generated file

Suppressed comments (1)

devtools/bindings/src/usePayCardToolProps.ts:197

  • balance.total is always set from useCardLinkedWallets().total, which defaults to 0 when the queries are skipped/uninitialized. That means the Balance screen can momentarily show a real-looking 0 even before any wallets were fetched/priced, which undermines the intent of rendering the raw value (including undefined) to distinguish “not loaded” from “zero”.
  const balance = useMemo(
    () => ({
      total: linkedWallets.total,
      isPartialTotal: linkedWallets.isPartialTotal,
      wallets: linkedWallets.wallets,
      isFetching: linkedWallets.isFetching,
      errors,
      load: loadWallets,
      refresh: refreshWallets,
    }),
    [linkedWallets, errors, loadWallets, refreshWallets],
  );
  • Files reviewed: 14/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@philipptpunkt
philipptpunkt force-pushed the fix/pay-card-schema-failure-detail branch from 7b9c907 to 5a63cad Compare September 2, 2026 14:53
Copilot AI review requested due to automatic review settings September 2, 2026 14:53
@philipptpunkt
philipptpunkt force-pushed the feat/pay-card-devtools-balance branch from 218ab25 to a4e58a4 Compare September 2, 2026 14:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The changes are self-contained, follow the stated lazy-fetching/pricing-resolver design, and include targeted unit/integration test updates plus a changeset.

Review details

Files not reviewed (1)

  • pnpm-lock.yaml: Generated file
  • Files reviewed: 14/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@philipptpunkt
philipptpunkt force-pushed the fix/pay-card-schema-failure-detail branch from 5a63cad to 3cded4d Compare September 2, 2026 15:23
Copilot AI review requested due to automatic review settings September 2, 2026 15:23
@philipptpunkt
philipptpunkt force-pushed the feat/pay-card-devtools-balance branch from a4e58a4 to 9aad82b Compare September 2, 2026 15:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The changes are cohesive, MVVM-compatible on mobile, include a changeset, and add/adjust targeted tests for the new Balance devtool behavior.

Review details

Files not reviewed (1)

  • pnpm-lock.yaml: Generated file
  • Files reviewed: 14/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@philipptpunkt
philipptpunkt force-pushed the fix/pay-card-schema-failure-detail branch from 3cded4d to a7701d0 Compare September 2, 2026 15:44
@philipptpunkt
philipptpunkt force-pushed the feat/pay-card-devtools-balance branch from 9aad82b to f8d18cd Compare September 2, 2026 15:44
Copilot AI review requested due to automatic review settings September 2, 2026 15:55
@philipptpunkt
philipptpunkt force-pushed the feat/pay-card-devtools-balance branch from f8d18cd to 6c9487f Compare September 2, 2026 15:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The Balance screen/binding currently risks displaying misleading “0”/misattributed null states, which undermines the devtool’s debugging purpose.

Review details

Files not reviewed (1)

  • pnpm-lock.yaml: Generated file

Suppressed comments (2)

devtools/pay-card/src/components/Balance/Balance.native.tsx:44

  • counterValue === null can mean either “no internal wallet matched” (balance is null) or “could not price” (no rate / mapping). The current message always claims a pricing/mapping issue, which is incorrect for wallets with balance: null and can mislead debugging.
      <Field
        label="counterValue"
        value={
          wallet.counterValue === null
            ? "null — no currency matched this ticker, or no rate for it"

devtools/bindings/src/usePayCardToolProps.ts:227

  • When resolveCounterValue is omitted, wallet queries are skipped, but the Balance props still surface total: 0 (from combining empty caches). That conflicts with the option doc (“report no balance rather than a wrong zero”) and makes “uninitialized / disabled” indistinguishable from a real 0 balance. Consider returning undefined until pricing is available (and while the first load is in progress).
      total: linkedWallets.total,
  • Files reviewed: 14/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

The linked-wallet total has no UI that shows the number itself, so a wrong
total cannot be told apart from a wrong formatter. The devtool shows what the
calculation returned.

- Opening the screen requests the wallets: the queries are skipped until then,
  so the tool does not fetch a cardholder's wallets to render a list of flags.
- The total is rendered raw, in the counter-value currency's smallest unit.
  Formatting it would hide the unit bug this screen exists to catch.
- A partial total says so. A wallet the rates could not price is left out of the
  sum rather than counted as zero, which otherwise reads as a complete total.
- Pricing needs the app's rates and currency settings, so the host passes its
  resolver in, the same way the card visual gets one.
Copilot AI review requested due to automatic review settings September 2, 2026 16:31
@philipptpunkt
philipptpunkt force-pushed the feat/pay-card-devtools-balance branch from 6c9487f to fe47991 Compare September 2, 2026 16:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The bindings currently expose a misleading 0 balance total while queries are skipped/unavailable, conflicting with the intended “no balance rather than wrong zero” behavior.

Review details

Files not reviewed (1)

  • pnpm-lock.yaml: Generated file

Suppressed comments (1)

devtools/bindings/src/usePayCardToolProps.ts:230

  • balance.total is always set to linkedWallets.total (which defaults to 0 when queries are skipped or before data arrives). This contradicts the stated intent of “report no balance rather than a wrong zero” when resolveCounterValue is absent / wallets haven’t been requested yet, and makes the Balance screen briefly show 0 as a real total.
  const balance = useMemo(
    () => ({
      total: linkedWallets.total,
      isPartialTotal: linkedWallets.isPartialTotal,
      wallets: linkedWallets.wallets,
      isFetching: linkedWallets.isFetching,
  • Files reviewed: 14/15 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@sonarqubecloud

sonarqubecloud Bot commented Sep 2, 2026

Copy link
Copy Markdown

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

Labels

devtools Has changes in the DevTools packages mobile Has changes in LLM

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants