Skip to content

Wallet simplified#3175

Merged
feruzm merged 7 commits intodevelopmentfrom
wallet
Apr 21, 2026
Merged

Wallet simplified#3175
feruzm merged 7 commits intodevelopmentfrom
wallet

Conversation

@feruzm
Copy link
Copy Markdown
Member

@feruzm feruzm commented Apr 20, 2026

Summary by CodeRabbit

  • New Features

    • QR code sharing for receiving payments
    • Peak Vault support for dApp signing flows
    • Token picker to switch tokens on the transfer screen
    • Quick wallet actions: Send, Receive, Swap, Get Points
    • Video player now supports thumbnail previews
  • Updates

    • Wallet header redesigned with refreshed layout and quick actions
    • Platform-specific typing behavior enabled for text editors/inputs on iOS
    • Expanded localization for wallet and transfer UI
    • Ecency SDK dependency updated

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Peak Vault dApp bridge (injected JS + handler), a Receive QR action sheet, token switching in transfers, wallet header quick-actions redesign, video thumbnail propagation to VideoPlayer, i18n additions, multiple TextInput platform tweaks, and bumps @ecency/sdk.

Changes

Cohort / File(s) Summary
Dependency & Locales
package.json, src/config/locales/en-US.json
Bumped @ecency/sdk to ^2.2.5; added/updated wallet and transfer translation keys and updated signing wording to include "Peak Vault".
Peak Vault Bridge & Types
src/screens/dappBrowser/bridges/bridgeTypes.ts, src/screens/dappBrowser/bridges/peakVaultBridge.ts
Added PeakVaultRequest/PeakVaultResponse interfaces and PEAK_VAULT_BRIDGE_JS — injected script exposing window.peakvault, dispatching peak-vault-event, and awaiting peak-vault-response-<resId>.
Bridge Handler Integration
src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts, src/screens/dappBrowser/screen/dappBrowser.tsx
Handle incoming pvRequest messages; validate account/PIN, support connect/sign/broadcast flows, emit response events; inject Peak Vault bridge for HTTPS pages.
Receive QR Sheet & Registration
src/components/receiveQrSheet/receiveQrSheet.tsx, src/navigation/sheets.tsx
New ReceiveQrSheet component (QR + copy username); added RECEIVE_QR sheet and augmented sheet typings with payload { username: string }.
Transfer: token switching
src/containers/transferContainer.ts, src/screens/transfer/index.tsx, src/screens/transfer/screen/transferScreen.tsx, src/screens/transfer/screen/transferStyles.ts
Added _setFundType and forwarded setFundType to views; fund badge now pressable to open token picker overlay, switch fundType, clear amount on change, and refetch balance.
Wallet header & quick actions
src/screens/wallet/children/walletHeader.tsx, src/screens/wallet/children/walletHeader.styles.ts
Reworked header layout/styles, replaced animated controls with touchable icons, added quick actions: Send, Swap, Receive (opens sheet), Get Points; adjusted sizing/typography and last-updated fallback.
Wallet asset UI & spacing
src/screens/wallet/children/assetCard.tsx, src/screens/wallet/children/claimButton.tsx, src/screens/wallet/screen/walletScreen.tsx, src/screens/wallet/styles/children.styles.ts, src/screens/wallet/styles/claimButton.styles.ts
Adjusted claim button sizing/margins and spacing; removed POINTS-specific footer rendering and related imports.
Asset details
src/screens/assetDetails/children/coinSummary.tsx
Conditionally render HorizontalIconList when token symbol is POINTS.
Video thumbnail propagation & player
src/components/postElements/body/view/postBodyView.tsx, src/components/postHtmlRenderer/postHtmlRenderer.tsx, src/components/postHtmlRenderer/postInteractionHandler.tsx, src/components/videoPlayer/videoPlayerView.tsx
Propagated optional thumbnailUrl through video handlers and players, updated handler signatures/refs, adjusted portrait aspect-ratio cap to 16:9, switched resizeMode to follow screenType, and deferred orientation lock on fullscreen exit.
Link processing deeplink relax
src/hooks/useLinkProcessor.tsx
Relaxed transfer deep-link validation to accept recipient-only deeplinks and navigate to transfer screen with pre-filled referredUsername and sensible fundType.
TextInput platform tweaks
src/components/editorElements/..., src/components/markdownEditor/..., src/components/quickPostModal/..., src/screens/chats/children/ThreadComposer.tsx, src/screens/editor/children/postDescription.tsx
Enabled iOS-specific text assistance (autoCorrect/spellCheck) and adjusted autoComplete handling for iOS across several text inputs.
PostHtmlRenderer API updates
src/components/postHtmlRenderer/*, src/components/postHtmlRenderer/postInteractionHandler.tsx
Updated handleVideoPress prop/signature to accept optional thumbnailUrl and threaded thumbnail state through interaction handler/ref.
Misc small UI tweaks
src/components/receiveQrSheet/..., src/components/postElements/..., other small files
Added copy-to-clipboard in Receive QR sheet; threaded video thumbnail state; minor style/layout adjustments across wallet and claim components.

Sequence Diagram(s)

sequenceDiagram
    participant WebView
    participant InjectedBridge as PeakVaultBridge
    participant BridgeHandler as Native Bridge Handler
    participant Account as Account State
    participant NativeUI as Native UI

    WebView->>InjectedBridge: window.peakvault.* invokes API -> dispatch pvRequest detail
    InjectedBridge->>BridgeHandler: postMessage { name: 'pvRequest', data }
    BridgeHandler->>Account: validate login & account match
    alt account valid
        BridgeHandler->>NativeUI: show SIGN_CONFIRM sheet
        NativeUI->>BridgeHandler: user approve / reject
        alt approve & broadcast
            BridgeHandler->>BridgeHandler: broadcast transaction
            BridgeHandler->>InjectedBridge: postMessage peak-vault-response (success/result)
        else approve & sign-only
            BridgeHandler->>Account: derive key via PIN, sign payload
            BridgeHandler->>InjectedBridge: postMessage peak-vault-response (signature + pubkey)
        end
    else invalid
        BridgeHandler->>InjectedBridge: postMessage peak-vault-response (error)
    end
    InjectedBridge->>WebView: dispatch peak-vault-response-<resId> event -> resolve Promise
Loading
sequenceDiagram
    participant User
    participant TransferUI as Transfer View
    participant TransferContainer
    participant BalanceSvc as Balance Fetch

    User->>TransferUI: tap fund badge
    TransferUI->>TransferUI: open token picker overlay
    User->>TransferUI: select token
    TransferUI->>TransferContainer: call setFundType(newType)
    TransferContainer->>TransferContainer: set fundType, reset balance
    TransferContainer->>BalanceSvc: fetchBalance(account.name)
    BalanceSvc->>TransferContainer: return balance
    TransferUI->>TransferUI: close picker, clear amount if token changed
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

deploy-pr-build

Poem

🐇 I hopped a bridge and drew a QR,
Pixels, tokens, thumbnails near and far,
Peak Vault sings, the webview hums,
Pick a fund, the picker drums,
A rabbit cheers — code stitched with care!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Wallet simplified' is overly vague and generic. While wallet-related changes are present, the PR encompasses far more than wallet simplification, including new components (ReceiveQrSheet, PeakVault bridge), transfer functionality enhancements, video player improvements, text input platform-specific behavior, and dependency updates across multiple systems. Use a more specific title that captures the primary changes, such as 'Add receive QR sheet and peak vault bridge support' or 'Enhance transfer UI with fund type switching and wallet header redesign' to better reflect the scope of changes.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch wallet

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.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@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.

Actionable comments posted: 4

♻️ Duplicate comments (1)
src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts (1)

313-329: ⚠️ Potential issue | 🟠 Major

Gate peakvault-connect behind user confirmation.

This still exposes the logged-in account to the page without consent. Please require the same confirmation sheet flow before returning result: [username].

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

In `@src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts` around lines 313 -
329, The current peakvault-connect branch in useHiveBridgeHandler sends account
info via _sendPvResponse without user consent; change it to invoke the app's
confirmation sheet flow (the same confirmation flow used elsewhere in this file)
before returning result: [username]: if !username keep the existing _sendPvError
behavior, otherwise present the confirmation UI to the user and only call
_sendPvResponse({ success: true, error: '', account: username, result:
[username] }) when the user explicitly confirms; if the user rejects or times
out, return an appropriate _sendPvError and do not expose username.
🧹 Nitpick comments (2)
src/components/postHtmlRenderer/postHtmlRenderer.tsx (2)

329-350: Thumbnail resolution for anchor-rendered videos LGTM.

Preferring the inline video-thumbnail <img src> and falling back to _metadataThumbUrl is a sensible precedence, and forwarding thumbnailUrl={thumbUri} into VideoPlayer aligns with the new prop threaded through postBodyView/postInteractionHandler. One minor readability nit: .indexOf('video-thumbnail') >= 0 could be .classes?.includes('video-thumbnail') for consistency with the same check done via includes elsewhere in this file (e.g. line 431, 477) and to tolerate any child shape lacking classes.

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

In `@src/components/postHtmlRenderer/postHtmlRenderer.tsx` around lines 329 - 350,
Replace the brittle ".classes.indexOf('video-thumbnail') >= 0" check inside the
tnode.children.find call with a safe includes check so children missing classes
don't throw: use child.classes?.includes('video-thumbnail') (referencing the
tnode.children.find and imgElement symbols) to locate the thumbnail img; keep
the existing fallback to _metadataThumbUrl and the rest of the rendering logic
unchanged.

140-141: Narrow the memo dependency to metadata?.image.

_metadataThumbUrl only reads metadata?.image, but the memo re-runs whenever the whole metadata reference changes (which in this codebase happens on most re-renders). Narrowing the dep keeps the value stable across unrelated metadata churn and avoids redundant invalidation of _handleOnLinkPress, _anchorRenderer, and _iframeRenderer callbacks that depend on it.

♻️ Proposed tweak
-    const _metadataThumbUrl = useMemo(() => _getFirstMetaImage(metadata?.image), [metadata]);
+    const _metadataThumbUrl = useMemo(
+      () => _getFirstMetaImage(metadata?.image),
+      [metadata?.image],
+    );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/postHtmlRenderer/postHtmlRenderer.tsx` around lines 140 - 141,
The useMemo that computes _metadataThumbUrl currently depends on the entire
metadata object which causes unnecessary recomputations; change the dependency
array on the useMemo that calls _getFirstMetaImage to only depend on
metadata?.image (i.e., useMemo(() => _getFirstMetaImage(metadata?.image),
[metadata?.image])) so _metadataThumbUrl stays stable across unrelated metadata
object changes and prevents needless invalidation of _handleOnLinkPress,
_anchorRenderer, and _iframeRenderer callbacks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts`:
- Line 311: The code reads keyRole from pvData (const { resId, account:
requestedAccount, operations, keyRole, broadcast } = pvData) but uses it
directly to pick an authority, allowing malformed/unknown values from the
WebView to silently fall back to different authorities; instead validate keyRole
against an explicit allowed set (e.g., const ALLOWED_KEY_ROLES =
['posting','active','owner']) before using it, and if keyRole is
missing/invalid: fail fast (reject the request or return an error response)
rather than defaulting differently for UI vs broadcast. Update every place that
branches on keyRole (the destructuring site and the similar logic around the
other blocks you noted) to perform the same validation and use the validated
value (or abort) so UI and broadcast behavior remain consistent.
- Around line 505-535: The sign-only unsupported error should be returned
immediately instead of first reading PIN/local keys; in the sign-only branch
call _sendPvError(resId, 'Sign-only mode is not supported in Ecency browser.
Please use requestBroadcast instead.', account) and return before accessing
store.getState(), getDigitPinCode, selectCurrentAccount, getActiveKey or
getPostingKey so key material is not touched when we always reject sign-only
requests.
- Around line 552-555: The pvRequest handling currently trusts pvData.sourceUrl
from the message; update useHiveBridgeHandler to accept the current trusted
WebView URL (e.g., trustedWebViewUrl) and, inside the onMessage/parsed.name ===
'pvRequest' branch before calling _handlePeakVaultMessage or showing
confirmation, validate that the origin/domain extracted from pvData.sourceUrl
strictly matches the trustedWebViewUrl (or its origin) and reject/ignore the
request if it does not match; reference the _handlePeakVaultMessage call, the
onMessage handler that checks parsed.name === 'pvRequest', and the
pvData.sourceUrl value when adding this gate.

In `@src/screens/wallet/children/walletHeader.tsx`:
- Around line 48-77: _onSendPress and _onSwapPress navigate unconditionally even
when no user is signed in; mirror the guard used in
_onReceivePress/_onGetPointsPress by checking currentAccount?.name before
calling navigation.navigate, and if falsy dispatch the same toastNotification
(using intl.formatMessage({ id: 'alert.not_logged_in' })) instead of navigating;
otherwise proceed to call navigation.navigate with the existing params for
ROUTES.SCREENS.TRANSFER and ROUTES.SCREENS.TRADE respectively.

---

Duplicate comments:
In `@src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts`:
- Around line 313-329: The current peakvault-connect branch in
useHiveBridgeHandler sends account info via _sendPvResponse without user
consent; change it to invoke the app's confirmation sheet flow (the same
confirmation flow used elsewhere in this file) before returning result:
[username]: if !username keep the existing _sendPvError behavior, otherwise
present the confirmation UI to the user and only call _sendPvResponse({ success:
true, error: '', account: username, result: [username] }) when the user
explicitly confirms; if the user rejects or times out, return an appropriate
_sendPvError and do not expose username.

---

Nitpick comments:
In `@src/components/postHtmlRenderer/postHtmlRenderer.tsx`:
- Around line 329-350: Replace the brittle ".classes.indexOf('video-thumbnail')
>= 0" check inside the tnode.children.find call with a safe includes check so
children missing classes don't throw: use
child.classes?.includes('video-thumbnail') (referencing the tnode.children.find
and imgElement symbols) to locate the thumbnail img; keep the existing fallback
to _metadataThumbUrl and the rest of the rendering logic unchanged.
- Around line 140-141: The useMemo that computes _metadataThumbUrl currently
depends on the entire metadata object which causes unnecessary recomputations;
change the dependency array on the useMemo that calls _getFirstMetaImage to only
depend on metadata?.image (i.e., useMemo(() =>
_getFirstMetaImage(metadata?.image), [metadata?.image])) so _metadataThumbUrl
stays stable across unrelated metadata object changes and prevents needless
invalidation of _handleOnLinkPress, _anchorRenderer, and _iframeRenderer
callbacks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a136bbbd-4455-45d2-b134-b9284569afdc

📥 Commits

Reviewing files that changed from the base of the PR and between d92e5b4 and ba852a3.

📒 Files selected for processing (4)
  • src/components/postHtmlRenderer/postHtmlRenderer.tsx
  • src/hooks/useLinkProcessor.tsx
  • src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts
  • src/screens/wallet/children/walletHeader.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/hooks/useLinkProcessor.tsx

Comment thread src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts
Comment thread src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts Outdated
Comment on lines +552 to +555
// Handle Peak Vault messages
if (parsed.name === 'pvRequest') {
_handlePeakVaultMessage((parsed as PeakVaultRequest).data);
return;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Inspect WebView wiring for Peak Vault injection vs message handling.
# Expectation: PEAK_VAULT_BRIDGE_JS is gated by HTTPS, and onMessage/handleMessage is still registered on the WebView.

fd -i '^dappBrowser\.tsx$' src | xargs rg -n -C3 \
  'injectedJavaScriptBeforeContentLoaded|PEAK_VAULT_BRIDGE_JS|onMessage|handleMessage|useHiveBridgeHandler'

Repository: ecency/ecency-mobile

Length of output: 1359


🏁 Script executed:

#!/bin/bash
# Read the useHiveBridgeHandler.ts file to inspect the _handlePeakVaultMessage function
# and understand how pvData.sourceUrl is used

# First, find the file
fd -i 'useHiveBridgeHandler.ts' src

# Get file size to determine reading strategy
wc -l src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts

Repository: ecency/ecency-mobile

Length of output: 175


🏁 Script executed:

#!/bin/bash
# Read around lines 552-555 and surrounding context to understand the flow
sed -n '540,600p' src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts

Repository: ecency/ecency-mobile

Length of output: 1867


🏁 Script executed:

#!/bin/bash
# Find _handlePeakVaultMessage function definition
rg -n '_handlePeakVaultMessage' src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts -A 20

Repository: ecency/ecency-mobile

Length of output: 1738


🏁 Script executed:

#!/bin/bash
# Check if there's any URL validation or trusted URL comparison before handling pvRequest
rg -n 'pvRequest|sourceUrl|pvData' src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts -B 2 -A 5

Repository: ecency/ecency-mobile

Length of output: 1632


🏁 Script executed:

#!/bin/bash
# Check if activeWebViewRef or tab.url is used anywhere for validation
rg -n 'activeWebViewRef|tab\.url|webViewUrl|currentUrl' src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts -B 2 -A 2

Repository: ecency/ecency-mobile

Length of output: 46


🏁 Script executed:

#!/bin/bash
# Check the beginning of the file to see what's passed to the hook
head -100 src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts

Repository: ecency/ecency-mobile

Length of output: 3071


Gate Peak Vault requests with the trusted WebView URL before processing.

The HTTPS-only injection check is bypassed when onMessage receives { name: 'pvRequest' } directly from untrusted page JavaScript. The pvData.sourceUrl is attacker-controlled, and the domain extracted from it (lines 358, 460) is displayed in the confirmation dialog without validating it matches the actual WebView URL. Pass the current trusted WebView URL to useHiveBridgeHandler and verify it matches pvData.sourceUrl before routing the request and showing the confirmation sheet.

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

In `@src/screens/dappBrowser/hooks/useHiveBridgeHandler.ts` around lines 552 -
555, The pvRequest handling currently trusts pvData.sourceUrl from the message;
update useHiveBridgeHandler to accept the current trusted WebView URL (e.g.,
trustedWebViewUrl) and, inside the onMessage/parsed.name === 'pvRequest' branch
before calling _handlePeakVaultMessage or showing confirmation, validate that
the origin/domain extracted from pvData.sourceUrl strictly matches the
trustedWebViewUrl (or its origin) and reject/ignore the request if it does not
match; reference the _handlePeakVaultMessage call, the onMessage handler that
checks parsed.name === 'pvRequest', and the pvData.sourceUrl value when adding
this gate.

Comment thread src/screens/wallet/children/walletHeader.tsx
@feruzm feruzm merged commit 43e8474 into development Apr 21, 2026
1 of 4 checks passed
@feruzm feruzm deleted the wallet branch April 21, 2026 08:07
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.

1 participant