Skip to content

feat(defi): show DeFi positions under the token table in chain view#252

Merged
BitHighlander merged 1 commit into
keepkey:developfrom
sktbrd:feat/defi-positions
Jun 17, 2026
Merged

feat(defi): show DeFi positions under the token table in chain view#252
BitHighlander merged 1 commit into
keepkey:developfrom
sktbrd:feat/defi-positions

Conversation

@sktbrd

@sktbrd sktbrd commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

EVM asset pages now display DeFi positions (staked / supplied / borrowed / LP / claimable protocol holdings) in their own section directly below the existing token table, sourced from the KeepKey Zapper proxy (GET /api/v1/zapper/portfolio/{address}). The normal token list is unchanged.

How DeFi positions are classified

An item from the Zapper response is marked DeFi when any of these are present:

  • tokenType === 'contract-position'
  • appId
  • groupId
  • metaType

Each is normalized with is_defi: boolean and protocol: appId ?? null, plus display fields (name, symbol, network, type, metaType, balance, balanceUsd, icon). Plain wallet tokens are dropped — Pioneer already serves those, so the DeFi section never duplicates the token table.

Backend

  • src/bun/zapper.ts (new) — pure classifyDefiPosition / normalizeDefiPositions helpers + fetchDefiPositions(address). The fetch resolves the same base URL as every other Pioneer call and degrades to [] on any error (DeFi is supplementary).
  • getDefiPositions({ address }) RPC — mirrors the existing getStakingPositions handler. Live-fetched, display-only (not added to chain/portfolio totals), and not persisted (passphrase-safe).

Frontend

  • DefiPositionsPanel.tsx (new) — lazy-loaded, rendered below the token table on EVM chains only, for the active address.
  • Values use the existing useFiat() formatting, so they respect the user's selected currency (shows R$ when BRL is selected).
  • Reuses the position icon when provided; applies the same hide-dust behavior as the token list (zero-USD positions tucked behind a show/hide toggle).
  • i18n keys added for en and pt.

Scope boundaries (by design)

  • DeFi USD is display-only this PR — not folded into chain balanceUsd or portfolio totals (avoids double-counting against Pioneer's token entries and keeps cache/total/passphrase logic untouched).
  • DeFi positions are not cached to SQLite — live-fetched on AssetPage mount, like staking.

Testing

  • bun test __tests__/defi-classify.test.ts14 passing unit tests covering the DeFi detection rules, protocol mapping, field-normalization fallbacks, response-shape unwrapping, and malformed-input tolerance.
  • ⚠️ Full typecheck/build requires the hdwallet submodule pipeline (make modules-build), which was not run in this environment.

🤖 Generated with Claude Code

EVM asset pages now display DeFi positions (staked / supplied / borrowed /
LP / claimable protocol holdings) in their own section below the existing
token table, sourced from the KeepKey Zapper proxy
(GET /api/v1/zapper/portfolio/{address}).

Backend:
- New src/bun/zapper.ts with pure classifyDefiPosition / normalizeDefiPositions
  helpers. An item is DeFi when any of tokenType === 'contract-position',
  appId, groupId, or metaType is present; each is normalized with
  is_defi + protocol (= appId) plus display fields. Plain wallet tokens are
  dropped (Pioneer already serves those) so the section never duplicates them.
- fetchDefiPositions() hits the Zapper proxy at the resolved Pioneer base URL,
  degrading to [] on any error (DeFi is supplementary).
- New getDefiPositions RPC (mirrors getStakingPositions); live-fetched,
  display-only, not persisted.

Frontend:
- New DefiPositionsPanel renders below the token table on EVM chains only,
  per active address. Values use the existing useFiat() formatting (shows BRL
  when selected). Reuses the position icon when present and applies the same
  hide-dust (zero-USD behind a toggle) behavior as the token list.
- Normal token list is unchanged.

Tests: 14 unit tests for the classification/normalization logic.

Note: full typecheck/build requires the hdwallet submodule pipeline
(make modules-build), not run in this environment.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sktbrd
sktbrd changed the base branch from master to develop June 17, 2026 23:38
@BitHighlander
BitHighlander merged commit b61ca9b into keepkey:develop Jun 17, 2026
0 of 3 checks passed
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