Skip to content

feat(ios): add iOS home-screen token widget with 24h change + sparkline#32132

Draft
ChingizMardanov wants to merge 2 commits into
mainfrom
swaps-assets-ios-widget
Draft

feat(ios): add iOS home-screen token widget with 24h change + sparkline#32132
ChingizMardanov wants to merge 2 commits into
mainfrom
swaps-assets-ios-widget

Conversation

@ChingizMardanov

Copy link
Copy Markdown

Adds the iOS token widget (App Group bridge, payload builder, sync manager, SwiftUI views) and enriches each row with the real 24h price change (green/red with a ▲/▼ arrow) and a mini price chart. Row/container margins tightened so more content fits.

The 24h change is sourced synchronously from Redux market data (mirroring useTokenPricePercentageChange). Sparkline data is currently mock but produced by a modular buildSparkline() so a real historical-price fetch can be dropped in later — the rest of the pipeline already passes a number[] through unchanged.

Description

Changelog

CHANGELOG entry:

Related issues

Fixes:

Manual testing steps

Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]

Screenshots/Recordings

Before

After

Pre-merge author checklist

Performance checks (if applicable)

  • I've tested on Android
    • Ideally on a mid-range device; emulator is acceptable
  • I've tested with a power user scenario
    • Use these power-user SRPs to import wallets with many accounts and tokens
  • I've instrumented key operations with Sentry traces for production performance metrics

For performance guidelines and tooling, see the Performance Guide.

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Adds the iOS token widget (App Group bridge, payload builder, sync manager,
SwiftUI views) and enriches each row with the real 24h price change (green/red
with a ▲/▼ arrow) and a mini price chart. Row/container margins tightened so
more content fits.

The 24h change is sourced synchronously from Redux market data (mirroring
useTokenPricePercentageChange). Sparkline data is currently mock but produced
by a modular buildSparkline() so a real historical-price fetch can be dropped
in later — the rest of the pipeline already passes a number[] through unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

CLA Signature Action:

Thank you for your submission, we really appreciate it. We ask that you read and sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just by adding a comment to this pull request with this exact sentence:

I have read the CLA Document and I hereby sign the CLA

By commenting with the above message you are agreeing to the terms of the CLA. Your account will be recorded as agreeing to our CLA so you don't need to sign it again for future contributions to this repository.

0 out of 1 committers have signed the CLA.
@ChingizMardanov

@metamask-ci metamask-ci Bot added the team-swaps-and-bridge Swaps and Bridge team label Jun 21, 2026
@metamask-ci

metamask-ci Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

PR template — items to address before "Ready for review"

Blocking — these items fail the workflow until fixed:

  • Changelog section has an empty CHANGELOG entry: line. Fill in a description, write CHANGELOG entry: null, or apply the no-changelog label.

Warnings — informational, address before merging:

  • Description section is empty. Describe what changed and why.
  • Related issues section is empty. Add Fixes: #123 / Closes: <URL> / Refs: <Jira key>, or write a short rationale after the colon.
  • Manual testing steps still contain template content (the Gherkin example title or a [...] placeholder). Replace with real steps, or write N/A — <reason>.
  • Screenshots/Recordings section is empty. Add an image/video for user-facing changes, logs/console output for non-user-facing changes, or write N/A if no evidence is applicable.
  • Pre-merge author checklist has unchecked items (e.g. "I've followed MetaMask Contributor Docs and MetaMask Mobile Coding Standards."). Every box must be consciously checked — see docs/readme/ready-for-review.md.

See docs/readme/ready-for-review.md for the full Definition of Ready for Review.

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
64.7% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@github-actions

Copy link
Copy Markdown
Contributor

⚡ Performance Test Results

ℹ️ Performance test results are currently non-blocking and will not block this PR.

All tests passed · 2 tests · 1 device

📱 Devices tested (1)

Android: Google Pixel 8 Pro (v14.0)

✅ Passed Tests (2)
Test Platform Device Duration Team Recording
Aggregated Balance Loading Time, SRP 1 + SRP 2 + SRP 3 Android Google Pixel 8 Pro (v14.0) 8.43s @assets-dev-team 📹 Watch
Asset View, SRP 1 + SRP 2 + SRP 3 Android Google Pixel 8 Pro (v14.0) 2.37s @assets-dev-team 📹 Watch

Branch: swaps-assets-ios-widget · Build: Normal · Commit: 366d1d5 · View full run

…ative

The widget bridge previously did logo downloading, image downscaling, JSON
parsing and field-remapping in Swift (~196 lines). All of that moves to JS,
keeping only what RN can't do natively in the bridge.

- RCTWidgetBridge.swift slimmed to two methods: getLogosDirectoryPath (so JS
  can write into the App Group container) and a verbatim setTokens + reload.
  Removed processTokens/cacheLogo/downscale/sanitize and all URLSession/UIImage
  code.
- New syncWidgetLogos.ts downloads logos via react-native-fs straight into the
  App Group dir (skip-if-exists, skips empty/non-http/SVG); failures fall back
  to the widget monogram.
- buildWidgetPayload now emits the final widget field names (deeplink), so Swift
  does no remapping; WidgetSyncManager.sync pushes through the JS logo step.
- SwiftUI widget views unchanged (WidgetKit can't run RN — irreducible).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeAccounts, SmokeConfirmations, SmokeNetworkAbstractions, SmokeNetworkExpansion, SmokeSwap, SmokeStake, SmokeWalletPlatform, SmokeMoney, SmokePerps, SmokeMultiChainAPI, SmokePredictions, SmokeSeedlessOnboarding, SmokeBrowser, SmokeSnaps
  • Selected Performance tags: None (no tests recommended)
  • Risk Level: high
  • AI Confidence: 100%
click to see 🤖 AI reasoning details

E2E Test Selection:
Hard rule (global-infrastructure-change): Global infrastructure changed: app/core/Engine/Engine.ts. Running all tests.

Performance Test Selection:
The WidgetSyncManager subscribes to the Redux store with a 5-second debounce, but it no-ops when the native WidgetBridge module is absent (which is the case in E2E/performance test environments). The buildWidgetPayload reads from existing selectors without modifying them. No performance-sensitive flows (onboarding, login, launch, asset loading, swaps) are modified. The iOS widget is a new additive feature that doesn't affect measured performance scenarios.

View GitHub Actions results

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant