Skip to content

feat: add vault and portfolio activity timelines - #736

Merged
Seranged merged 84 commits into
developmentfrom
feature/lite-219-add-activity-events-section-to-vault-page-filterable-by
Jul 29, 2026
Merged

Seranged merged 84 commits into
developmentfrom
feature/lite-219-add-activity-events-section-to-vault-page-filterable-by

Conversation

@Seranged

@Seranged Seranged commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add normalized Activity timelines to EVK, Euler Earn, and Securitize vault overviews and to the portfolio Position Activity tab.
  • Share availability, filtering, pagination, responsive rows, and error-state behavior across vault and account scopes.
  • Keep Activity V3-only and hide unsupported scopes without presenting transport failures or incomplete coverage as empty history.

UX and presentation

  • Vault Activity shows core lending and borrowing operations alongside relevant governance, risk, liquidation, and vault-management events while suppressing interest accruals and duplicate companion transfers.
  • Portfolio Activity shows deposit, withdrawal, borrow, repay, debt-pull, and liquidation history for the active network, including spy-mode positions. Account-category events (operator, controller, and collateral status changes), share transfers, rewards, and swaps are outside the portfolio timeline's supported scope — none of those types are decoded into a user-meaningful presentation yet, so surfacing them would only add raw noise.
  • Event rows prioritize operation, amount or change, time, market, and participants, with compact and wide responsive layouts.
  • Token and vault metadata enrich raw events with images, symbols, decimals, and readable vault names.
  • Supply and borrow caps, LTV values, durations, and timestamps are decoded into human-readable values.
  • User identities link to portfolio spy mode; protocol actors and configuration addresses link to the block explorer; recognized vault addresses link to their Lite vault pages.
  • Vault timelines collapse exact paired operations such as deposit plus transfer while keeping independent vault share transfers visible.

Availability and data integrity

  • Availability combines the Lite V3 chain gate, SDK adapter capability, scoped chain and vault support, and runtime V3 coverage.
  • Unsupported scopes do not render Activity. Transient API, authentication, timeout, or schema failures remain retryable errors.
  • Loading, refreshing, syncing, partial coverage, valid empty history, stale-data retry, and cursor pagination are represented separately.
  • Source amounts and event-time valuations remain authoritative. Lite uses current static metadata only for presentation and does not fabricate missing historical prices or participants.
  • The internal V3 proxy allows normalized Activity routes, applies bounded upstream backoff, and sanitizes account and cursor data from logs.
  • The SDK Activity service provides the normalized account and vault event contract.

Test plan

  • Focused Activity, availability, display, proxy, and spy-mode tests passed
  • Changed-file ESLint passed
  • Diff and commit hooks passed
  • Smoke EVK vault and portfolio Activity against live V3 data at desktop and mobile sizes
  • Verify portfolio browser history restores the inspected spy-mode position and Activity route
  • Verify unsupported portfolio event categories are excluded from the request and UI
  • Consume @eulerxyz/euler-v2-sdk@1.2.0 and pass the full test, typecheck, and production-build gates
  • Smoke Euler Earn and Securitize vault Activity against the final deployed preview
  • Verify unsupported networks hide Activity without flashing an empty state
  • Verify filters, retry, refresh, scope changes, and load-more pagination against the final deployed preview

@railway-app
railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-736 July 13, 2026 12:18 Destroyed
@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

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 activity feeds with category filtering, formatted event rows, availability checks, pagination, refresh handling, and vault overview integration. Extends V3 activity proxy routing, structured logging, backoff keying, and bounded backoff storage.

Changes

Activity feed and vault integration

Layer / File(s) Summary
Activity display and event rendering
utils/activity-display.ts, components/entities/activity/*, tests/utils/activity-display.test.ts
Adds category filtering, address copying, responsive event rows, asset/change/participant formatting, valuation handling, and display helper tests.
Feed loading and availability
composables/useActivity*.ts, components/entities/activity/ActivityFeed.vue, utils/sdk-query-*, tests/composables/*
Adds capability gating, SDK-backed fetching, pagination, refresh and invalidation handling, coverage states, and race-condition tests.
Vault overview activity blocks
components/entities/vault/overview/*
Adds activity accordion blocks for EVK, Securitize, and Earn vaults, with runtime support checks and keep-mounted content.

V3 activity proxy support

Layer / File(s) Summary
Activity route validation and logging
server/utils/v3-proxy.ts, server/api/internal/v3/[...path].ts, tests/server/v3-proxy*.test.ts
Allows account and vault activity routes, validates bounded query parameters, records activity logging fields, and sanitizes upstream error logs.
Activity backoff keys and bounded storage
server/utils/v3-proxy-backoff.ts, tests/server/v3-proxy-backoff.test.ts
Adds sanitized activity-specific backoff keys, expiration pruning, oldest-entry eviction, and a maximum of 256 stored entries.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant VaultOverviewBlockActivity
  participant ActivityFeed
  participant useActivityAvailability
  participant useActivityFeed
  participant activityService
  VaultOverviewBlockActivity->>useActivityAvailability: check activity scope support
  VaultOverviewBlockActivity->>ActivityFeed: render supported activity scope
  ActivityFeed->>useActivityFeed: enable feed and selected categories
  useActivityFeed->>activityService: fetch activity events
  activityService-->>useActivityFeed: return events and coverage
  useActivityFeed-->>ActivityFeed: update feed state
  ActivityFeed-->>VaultOverviewBlockActivity: emit settled and support state
Loading

Possibly related PRs

Suggested reviewers: kasperpawlowski

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding activity timelines for vault and portfolio views.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/lite-219-add-activity-events-section-to-vault-page-filterable-by

Comment @coderabbitai help to get the list of available commands.

@railway-app

railway-app Bot commented Jul 13, 2026

Copy link
Copy Markdown

🚅 Deployed to the euler-lite-pr-736 environment in euler-lite(dev,PR previews)

Service Status Web Updated (UTC)
dev-build ✅ Success (View Logs) Web Jul 28, 2026 at 4:42 pm

- keep historical EVK categories independent of current borrowability
- distinguish partial coverage and bound proxy backoffs
@railway-app
railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-736 July 13, 2026 14:22 Destroyed
@Seranged
Seranged marked this pull request as ready for review July 17, 2026 08:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@components/entities/activity/ActivityEventRow.vue`:
- Line 2: Resolve the unsupported ActivityEvent import in ActivityEventRow by
either updating the SDK package to export ActivityEvent in its published
declarations or replacing the import with a supported type. Ensure the component
typechecks without relying on an unavailable `@eulerxyz/euler-v2-sdk` export.

In `@composables/useActivityAvailability.ts`:
- Around line 1-5: Publish or consume an SDK release that exports the Activity*
types and EulerSDK.activityService, then bump the `@eulerxyz/euler-v2-sdk`
dependency accordingly. Update composables/useActivityAvailability.ts (lines 1-5
and 77-78), composables/useActivityFeed.ts (lines 1-7 and 161-172),
components/entities/activity/ActivityFeed.vue (lines 2-4), and
components/entities/vault/overview/VaultOverviewBlockActivity.vue (lines 2-5) so
their existing Activity API imports and calls typecheck against the released
SDK.
🪄 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: Repository: euler-xyz/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3fc25f08-907c-4c9f-a747-73ea02e8d3c7

📥 Commits

Reviewing files that changed from the base of the PR and between 21a22e8 and d66c4c8.

📒 Files selected for processing (22)
  • components/entities/activity/ActivityCategoryFilters.vue
  • components/entities/activity/ActivityEventRow.vue
  • components/entities/activity/ActivityFeed.vue
  • components/entities/vault/overview/SecuritizeVaultOverview.vue
  • components/entities/vault/overview/VaultOverview.vue
  • components/entities/vault/overview/VaultOverviewAccordionSection.vue
  • components/entities/vault/overview/VaultOverviewBlockActivity.vue
  • components/entities/vault/overview/earn/VaultOverviewEarn.vue
  • composables/useActivityAvailability.ts
  • composables/useActivityFeed.ts
  • server/api/internal/v3/[...path].ts
  • server/utils/v3-proxy-backoff.ts
  • server/utils/v3-proxy.ts
  • tests/composables/useActivityAvailability.test.ts
  • tests/composables/useActivityFeed.test.ts
  • tests/server/v3-proxy-backoff.test.ts
  • tests/server/v3-proxy-route.test.ts
  • tests/server/v3-proxy.test.ts
  • tests/utils/activity-display.test.ts
  • utils/activity-display.ts
  • utils/sdk-query-cache.ts
  • utils/sdk-query-policy.ts

Comment thread components/entities/activity/ActivityEventRow.vue Outdated
Comment thread composables/useActivityAvailability.ts
Keep raw V3 activity available while Lite requests only scope-relevant display events and suppresses accrual and paired share-movement noise.
@railway-app
railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-736 July 17, 2026 08:31 Destroyed

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

Review summary

Verdict: changes requested — reviewed head d640f9252c333642f74c101e61377064c0c0971a.

The activity lifecycle, pagination, proxy allowlist/backoff sanitization, and desktop/mobile presentation are well structured and behaved correctly in targeted validation. The remaining blocker is the SDK integration boundary: this branch still declares/locks @eulerxyz/euler-v2-sdk@1.1.4, whose published declarations do not expose the Activity* types, activityService, or the new activity query names consumed here.

Consequences on the current head:

  • npm run typecheck fails across the production activity components/composables and query policy.
  • Hosted CI's full test run passes 1,282/1,283 tests; the sole failure is tests/utils/sdk-query-policy.test.ts because the installed SDK never presents the activity query names to the wrapper.

Please bump the dependency and lockfile to a published SDK release containing this API, then rerun typecheck and the full suite. This confirms the existing CodeRabbit SDK comments are valid; I did not duplicate them inline.

Validation

  • Focused activity/availability/display/proxy tests: passed.
  • Headed Railway preview smoke at desktop 1440×1100 and mobile 390×844 on /lend/0xba98…83b5?network=1: activity accordion opened; live events rendered; Governance filtering returned governance-only rows; returning to All and Load older increased rows from 25 to 50; activity requests returned HTTP 200.
  • Railway preview build: passed.
  • Wallet/signing smoke: not applicable; this is a read-only timeline.

Maintainability / security pass

The reusable logic is appropriately centralized in useActivityFeed, useActivityAvailability, activity-display, and the shared overview block used by EVK/Earn surfaces. Focused tests cover stale responses, refresh/pagination, formatting, proxy route restrictions, privacy-preserving backoff keys, and sanitized route-template logging. I found no additional blocker beyond the SDK publication/version gate.

Visual evidence

Desktop — open vault Activity section with filters and live rows:

Desktop vault activity

Mobile — 390×844 vault information modal with the open Activity section and horizontally scrollable filters:

Mobile vault activity

- clarify transfers and suppress exact paired share movements
- add token imagery, compact responsive details, and copyable addresses
- hide unavailable pricing noise while preserving truthful fallbacks
@railway-app
railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-736 July 17, 2026 10:12 Destroyed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@utils/activity-display.ts`:
- Around line 184-224: Update the companion-event lookup inside
filterActivityEventsForDisplay to search visibleEvents instead of the unfiltered
events collection, so transfer suppression only occurs for paired events that
pass the requested eventTypes allowlist. Preserve the existing group, type,
address, and amount matching logic.
🪄 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: Repository: euler-xyz/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4a95cc32-fb5b-45ca-877d-7ef7f076a526

📥 Commits

Reviewing files that changed from the base of the PR and between d640f92 and 9832063.

📒 Files selected for processing (7)
  • components/entities/activity/ActivityAddress.vue
  • components/entities/activity/ActivityEventRow.vue
  • components/entities/activity/ActivityFeed.vue
  • composables/useActivityFeed.ts
  • tests/composables/useActivityFeed.test.ts
  • tests/utils/activity-display.test.ts
  • utils/activity-display.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • composables/useActivityFeed.ts
  • components/entities/activity/ActivityFeed.vue
  • tests/utils/activity-display.test.ts
  • tests/composables/useActivityFeed.test.ts

Comment thread utils/activity-display.ts
Show historical amounts in underlying asset units and conservatively collapse exact paired operations.
@railway-app
railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-736 July 17, 2026 10:30 Destroyed
Use the available Activity feed width to switch between compact and full table layouts, keeping vault rows readable without changing the wider portfolio presentation.
@railway-app
railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-736 July 17, 2026 10:44 Destroyed
Group participant metadata with the event summary at constrained feed widths so vault activity stays dense while preserving the wide portfolio table.
@railway-app
railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-736 July 17, 2026 10:55 Destroyed
Emphasize event amounts, reduce redundant asset labels, and present expandable metadata as a compact accessible disclosure control.
@railway-app
railway-app Bot temporarily deployed to euler-lite / euler-lite-pr-736 July 17, 2026 11:03 Destroyed
Seranged added 6 commits July 17, 2026 12:03
- clarify transfers and suppress exact paired share movements
- add token imagery, compact responsive details, and copyable addresses
- hide unavailable pricing noise while preserving truthful fallbacks
Describe incomplete categories without implying that no events exist.
Limit position history to attributable operations, show asset-unit amounts, and conservatively collapse exact paired events.
@railway-app
railway-app Bot temporarily deployed to euler-lite(dev,PR previews) / euler-lite-pr-736 July 23, 2026 16:22 Destroyed

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

Reviewed current head 2e5bbe4b4b726c9536d0478491a78e8640d95e7b.

Requesting changes for two blocking issues:

  1. The pinned @eulerxyz/euler-v2-sdk@1.2.0 does not export LiquidationRecord, activityService.fetchLiquidations, or queryLiquidations. Node 24 / npm 11.10.0 typecheck reproduces five errors across the new liquidation display/composable/query-policy surface; the real production package takes the no-op fallback, while the focused test mocks the missing API.
  2. Pending spy-owner verification is not fail-closed across sibling consumers. useEulerAccount, useRewardsApy, useApyVisibility, and useREULLocks can fall back to the connected wallet while spy mode is active but spyAddress is intentionally empty.

Validation:

  • paginated 49-file manifest and all changed hunks reviewed
  • focused Activity/proxy/spy tests: 12 files / 108 tests passed
  • typecheck: failed with the five SDK-contract errors above
  • focused ESLint and git diff --check: passed
  • headed portfolio Activity smoke at 1440×1000 and 390×844: live account timeline loaded, Liquidations filter selected, row rendered
  • vault Activity variants and wallet/signing flows were not browser-smoked

Desktop evidence:
Desktop portfolio Activity with Liquidations selected

Mobile evidence:
Mobile portfolio Activity with Liquidations selected

The Activity feed/display/proxy logic is otherwise well centralized and substantially tested. The remaining spy-address selection should likewise become one shared fail-closed invariant rather than duplicated fallbacks. Existing inline threads carry the concrete anchors.

Six component/page sites still selected portfolioAddress || wallet for
sub-account index derivation, reopening the connected-wallet fall-through
one layer below the composables fixed previously. portfolioAddress is
already the spy-safe acting address and equals the wallet outside spy
mode, so the fallback was dead code normally and computed position
indices against the wrong owner while a spy candidate was verifying.
@railway-app
railway-app Bot temporarily deployed to euler-lite(dev,PR previews) / euler-lite-pr-736 July 24, 2026 09:48 Destroyed

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

Leonard review — changes requested

Reviewed head: a9b245f09102bb96a99a1f2ba68ab92ffed1de6f

Blocking

The SDK mismatch remains. package.json and the lockfile pin @eulerxyz/euler-v2-sdk 1.2.0, but this head imports LiquidationRecord, calls activityService.fetchLiquidations, and adds queryLiquidations. Those members are absent from the installed 1.2.0 declarations/runtime surface.

Consequences on this exact head:

  • Nuxt typecheck fails at the three LiquidationRecord import sites, fetchLiquidations, and the queryLiquidations policy row.
  • The full suite reports 1 failed / 1,322 passed because queryLiquidations was never wrapped by the SDK build.

The production build completes because it does not enforce the missing type/runtime contract; it does not clear this blocker.

Re-review result

The prior pending-spy fallback concern is resolved on this head. The affected composables now use useEffectiveAddress, and a9b245f0 removes the remaining connected-wallet fallbacks from the portfolio item/modal consumers. The focused Activity/spy/proxy run passed 106 tests.

The earlier bot thread confirming the base Activity API in 1.2.0 does not cover these later liquidation members; the installed declarations and runtime query-policy test are the discriminating evidence.

Smoke coverage

Exact-head local production build, headed Chromium:

  • Desktop 1440×1000: portfolio Activity → Liquidations, real liquidation event rendered; Activity requests returned 200.
  • Mobile 390×844: Activity tab and Liquidations filter selected; liquidation card visible without loading/error state or page exceptions.
  • Wallet/signing smoke: not run — this is a read-only timeline flow.

Desktop — portfolio Activity / Liquidations

Desktop portfolio Activity / Liquidations

Mobile 390×844 — selected Liquidations filter and event card

Mobile portfolio Activity / Liquidations

Current GitHub state also reports a merge conflict with development.

Conflict resolutions:
- package.json/lockfile: take development's dependency bumps (euler-v2-sdk
  1.2.1, floating-ui 2.0.1)
- v3 proxy error logging: combine both improvements — development's
  timeout classification (reason field, no err on aborts) with this
  branch's sanitized error fields; both regression tests kept
- sdk-query-policy: drop development's duplicate activity rows in favor of
  this branch's activity section (same stale times)
- new useRewardsApy tests: stub useEffectiveAddress, which this branch's
  spy-safe selection introduced
@railway-app
railway-app Bot temporarily deployed to euler-lite(dev,PR previews) / euler-lite-pr-736 July 24, 2026 10:25 Destroyed

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

Reviewed current head e5bd7a8aa31f5a5885e1e2e6cc223e25147bd696 using the anti-anchoring-v1 coverage protocol.

One blocker remains: the liquidation enrichment is compiled against a service method that is absent from the installed SDK. Exact-head npm run typecheck and GitHub's Test & Build job both fail on this contract mismatch; see the inline comment.

Validation:

  • focused Vitest: 12 files / 359 tests passed
  • targeted ESLint passed
  • production build passed
  • headed desktop and mobile vault Activity smoke passed visually
  • proxy/security, sibling-flow, maintainability, and fresh-challenge passes completed

The portfolio Activity route was code/test reviewed but not browser-smoked with a representative multi-chain account. Wallet/signing smoke is not applicable to this read-only change.

Full walkthrough and verified visual evidence: #736 (comment)

Comment thread composables/useActivityLiquidationDetails.ts
@railway-app
railway-app Bot temporarily deployed to euler-lite(dev,PR previews) / euler-lite-pr-736 July 27, 2026 10:34 Destroyed

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

Euler PR review

Reviewed the complete exact-head delta across 55 changed files; 6 causally attributable findings retained.

Findings

  • [MEDIUM] Liquidation enrichment join keys can collide for repeated same-amount liquidations (eprv2-07afa7a2ea65e6e45959)
    • Files: composables/useActivityLiquidationDetails.ts, tests/composables/useActivityLiquidationDetails.test.ts
    • Invariant: Each displayed liquidation event must join to at most its own historical liquidation record.
    • Impact: Two liquidation events in one transaction with the same chain, vault, violator, collateral, and repay amount map to the same key. The later record overwrites the earlier record, so both rows can display the same collateral conversion, USD valuation, and liquidator bonus even when their seized yield balances differ.
    • Production reachability: credible — Batched EVC transactions can contain repeated liquidation operations, and the event payload and liquidation record expose yield-balance data that can differ even when repay amounts match. The current key omits that available discriminator.
    • Evidence: composables/useActivityLiquidationDetails.ts:147-151, composables/useActivityLiquidationDetails.ts:37-66, tests/composables/useActivityLiquidationDetails.test.ts:20-52
    • Recommendation: Include every stable discriminator shared by both records, including yieldBalance or yield_balance and block identity where appropriate. Add a fixture with two same-transaction, same-repay liquidations having different yield balances and assert one-to-one enrichment.
  • [MEDIUM] Liquidation valuation UI is unreachable with the pinned SDK service (eprv2-43e8a25b0fece6e78053)
    • Files: components/entities/activity/ActivityEventRow.vue, components/entities/activity/ActivityFeed.vue, composables/useActivityLiquidationDetails.ts, package-lock.json, tests/composables/useActivityLiquidationDetails.test.ts
    • Invariant: A user-facing enrichment path introduced by the PR must be wired to a runtime dependency that exposes the required service method at the reviewed head.
    • Impact: The activity UI contains historical liquidation USD values, underlying collateral conversion, and liquidator bonus presentation, but the composable returns when activityService.fetchLiquidations is absent. The added contract test records that the pinned published SDK lacks this method, and the lockfile does not upgrade that SDK, so the enrichment path does not execute in the shipped dependency composition.
    • Production reachability: demonstrated — The added test explicitly models the pinned package as not exposing fetchLiquidations and expects a no-op. The lockfile delta does not provide a compatible Euler SDK upgrade, while the feed instantiates the enrichment composable.
    • Evidence: components/entities/activity/ActivityEventRow.vue:100-179, components/entities/activity/ActivityFeed.vue:43-48, composables/useActivityLiquidationDetails.ts:122-130, package-lock.json:2186-2213, tests/composables/useActivityLiquidationDetails.test.ts:60-84
    • Recommendation: Ship a compatible SDK version or reviewed local client implementation in the same dependency composition, then add a contract test against the real instantiated SDK service. If enrichment is intentionally deferred, remove or explicitly scope the currently unreachable feature claim.
  • [LOW] Activity backoff keys couple unrelated subjects and pagination requests (eprv2-846cfb17c62fb7747bb0)
    • Files: server/utils/v3-proxy-backoff.ts, tests/server/v3-proxy-backoff.test.ts
    • Invariant: A retryable upstream failure isolated to one activity subject or page should not impose a cooldown on unrelated users, vaults, or pages.
    • Impact: Account and vault addresses are normalized out of the in-memory backoff key, and cursors are omitted. A retryable failure while loading one subject or older page can therefore block head and pagination requests sharing the same chain and filter context for ten seconds.
    • Production reachability: credible — The added tests require different account and vault addresses to produce identical keys, and the proxy records cooldowns for retryable upstream statuses. The breadth of impact is deterministic once such a failure is recorded, although the cooldown is bounded and some failures may genuinely be endpoint-wide.
    • Evidence: server/utils/v3-proxy-backoff.ts:22-31, server/utils/v3-proxy-backoff.ts:45-80, tests/server/v3-proxy-backoff.test.ts:18-41, tests/server/v3-proxy-backoff.test.ts:73-89
    • Recommendation: Keep sensitive values out of logs while isolating internal cooldown state with a bounded one-way digest of the subject and cursor, or apply broad backoff only to failures established as endpoint-wide. Add tests showing distinct subjects and pagination cursors do not suppress one another.
  • [LOW] Covered liquidation windows can permanently skip newly indexed records (eprv2-85c40cb34385a1b59ccf)
    • Files: composables/useActivityLiquidationDetails.ts, tests/composables/useActivityLiquidationDetails.test.ts, utils/sdk-query-policy.ts
    • Invariant: When a refreshed feed introduces a liquidation event, its enrichment lookup must run unless that exact event's record is already known.
    • Impact: The composable treats a timestamp window as permanently covered after one successful request. If a later feed refresh reveals another liquidation for the same vault inside that window, the lookup returns without querying again and the new row remains unenriched for the mounted component's lifetime.
    • Production reachability: credible — Activity and liquidation indexing can settle at different times, and multiple events can share a block timestamp. SDK query invalidation does not clear or version the composable-local covered-window map, so it cannot force a reread when a new same-window event appears.
    • Evidence: composables/useActivityLiquidationDetails.ts:107-116, composables/useActivityLiquidationDetails.ts:157-172, tests/composables/useActivityLiquidationDetails.test.ts:65-103, utils/sdk-query-policy.ts:109-121
    • Recommendation: Track unresolved event join keys in addition to timestamp coverage, or permit a bounded refetch whenever a newly observed key is absent from known records. Add a regression test that appends a same-timestamp event after the initial lookup.
  • [HIGH] Spy owner resolution is not invalidated when the active chain changes (eprv2-86efd4cb890a0bbf8770)
    • Files: composables/useSpyMode.ts, tests/composables/useEffectiveAddress.test.ts, tests/composables/useSpyMode.test.ts
    • Invariant: A spy candidate may become the effective address only after owner resolution on the same chain and RPC context in which that candidate is consumed.
    • Impact: If the network changes while owner resolution is in flight, the old chain's owner result can be promoted after the switch. Portfolio, reward eligibility, lock balance, APY visibility, and activity reads can then target the wrong owner on the newly selected network.
    • Production reachability: credible — Network changes are normal wallet interactions. The resolution watcher observes the candidate, EVC address, and RPC client but not chainId, and the asynchronous result is not tagged with its originating chain. If those watched identities remain stable across a chain change, the prior request remains authoritative.
    • Evidence: composables/useSpyMode.ts:101-139, composables/useSpyMode.ts:149-157, tests/composables/useEffectiveAddress.test.ts:65-128, tests/composables/useSpyMode.test.ts:1-290
    • Recommendation: Include chainId in the resolution trigger and request identity. Capture the chain and client used by each lookup, invalidate the request generation on chain changes, and add a race test in which a chain-A lookup resolves after switching to chain B.
  • [MEDIUM] Exhausted owner-resolution retries leave spy mode permanently unusable (eprv2-c78e8c8767b0a565b22f)
    • Files: components/layout/SpyModeBanner.vue, composables/useSpyMode.ts, tests/composables/useSpyMode.test.ts
    • Invariant: A transient RPC failure must fail closed without permanently trapping the active spy session; users need an automatic recovery trigger or an explicit retry/error path.
    • Impact: After the initial lookup and five retries fail, the candidate remains pending indefinitely. Effective-address consumers stay blank, portfolio and reward/lock queries remain disabled, and the banner continues to show “Verifying address…” even if RPC service subsequently recovers.
    • Production reachability: credible — Owner lookup uses the configured RPC client, so an outage or rate limit can exhaust the bounded retry window. The committed test establishes that the resulting steady state remains active and unresolved without further scheduling.
    • Evidence: components/layout/SpyModeBanner.vue:15-27, composables/useSpyMode.ts:100-127, tests/composables/useSpyMode.test.ts:190-220
    • Recommendation: Preserve the fail-closed address boundary, but expose a failed/retryable state and retry action or restart resolution on a bounded recovery signal such as RPC-client or chain reconnection. Do not leave the resolving state true indefinitely after the retry budget is exhausted.

Coverage

  • Complete: yes
  • Changed files inventoried: 55
  • components/entities/activity/ActivityAddress.vue: complete
  • components/entities/activity/ActivityCategoryFilters.vue: complete
  • components/entities/activity/ActivityEventRow.vue: complete (findings=eprv2-43e8a25b0fece6e78053)
  • components/entities/activity/ActivityFeed.vue: complete (findings=eprv2-43e8a25b0fece6e78053)
  • components/entities/asset/AssetAvatar.vue: complete
  • components/entities/portfolio/PortfolioBorrowItem.vue: complete
  • components/entities/portfolio/PortfolioEarnItem.vue: complete
  • components/entities/portfolio/PortfolioSavingItem.vue: complete
  • components/entities/portfolio/PortfolioUnsupportedBorrowItem.vue: complete
  • components/entities/vault/ChooseCollateralModal.vue: complete
  • components/entities/vault/VaultLabelsAndAssets.vue: complete
  • components/entities/vault/overview/SecuritizeVaultOverview.vue: complete
  • components/entities/vault/overview/VaultOverview.vue: complete
  • components/entities/vault/overview/VaultOverviewAccordionSection.vue: complete
  • components/entities/vault/overview/VaultOverviewBlockActivity.vue: complete
  • components/entities/vault/overview/earn/VaultOverviewEarn.vue: complete
  • components/layout/SpyModeBanner.vue: complete (findings=eprv2-c78e8c8767b0a565b22f)
  • components/ui/UiCustomFilterChips.vue: complete
  • components/ui/UiFilterChip.vue: complete
  • components/ui/UiSelect.vue: complete
  • components/ui/UiTabs.vue: complete
  • composables/useActivityAvailability.ts: complete
  • composables/useActivityFeed.ts: complete
  • composables/useActivityLiquidationDetails.ts: complete (findings=eprv2-07afa7a2ea65e6e45959,eprv2-43e8a25b0fece6e78053,eprv2-85c40cb34385a1b59ccf)
  • composables/useActivityNowMs.ts: complete
  • composables/useApyVisibility.ts: complete
  • composables/useEulerAccount.ts: complete
  • composables/usePortfolioActivityRuntimeSupport.ts: complete
  • composables/useREULLocks.ts: complete
  • composables/useRewardsApy.ts: complete
  • composables/useSpyMode.ts: complete (findings=eprv2-86efd4cb890a0bbf8770,eprv2-c78e8c8767b0a565b22f)
  • middleware/02.spy-param.global.ts: complete
  • package-lock.json: complete (findings=eprv2-43e8a25b0fece6e78053)
  • pages/portfolio.vue: complete
  • pages/portfolio/activity.vue: complete
  • pages/portfolio/index.vue: complete
  • server/api/internal/v3/[...path].ts: complete
  • server/utils/v3-proxy-backoff.ts: complete (findings=eprv2-846cfb17c62fb7747bb0)
  • server/utils/v3-proxy.ts: complete
  • tests/composables/useActivityAvailability.test.ts: complete
  • tests/composables/useActivityFeed.test.ts: complete
  • tests/composables/useActivityLiquidationDetails.test.ts: complete (findings=eprv2-07afa7a2ea65e6e45959,eprv2-43e8a25b0fece6e78053,eprv2-85c40cb34385a1b59ccf)
  • tests/composables/useActivityNowMs.test.ts: complete
  • tests/composables/useEffectiveAddress.test.ts: complete (findings=eprv2-86efd4cb890a0bbf8770)
  • tests/composables/usePortfolioActivityRuntimeSupport.test.ts: complete
  • tests/composables/useREULLocks.test.ts: complete
  • tests/composables/useRewardsApy.test.ts: complete
  • tests/composables/useSpyMode.test.ts: complete (findings=eprv2-86efd4cb890a0bbf8770,eprv2-c78e8c8767b0a565b22f)
  • tests/server/v3-proxy-backoff.test.ts: complete (findings=eprv2-846cfb17c62fb7747bb0)
  • tests/server/v3-proxy-route.test.ts: complete
  • tests/server/v3-proxy.test.ts: complete
  • tests/utils/activity-display.test.ts: complete
  • utils/activity-display.ts: complete
  • utils/sdk-query-cache.ts: complete
  • utils/sdk-query-policy.ts: complete (findings=eprv2-85c40cb34385a1b59ccf)

Coverage gaps

  • None.

Validation

@railway-app
railway-app Bot temporarily deployed to euler-lite(dev,PR previews) / euler-lite-pr-736 July 27, 2026 13:12 Destroyed

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

Euler PR review

Reviewed the complete exact-head delta across 55 changed files; 1 causally attributable finding retained.

Findings

  • [MEDIUM] Spy-owner verification is not bound to the active chain (eprv2-ddff8351d02cb2bb5ac3)
    • Files: composables/useSpyMode.ts
    • Invariant: A spy candidate may become and remain the effective address only when its EVC ownership was resolved for the same chain and RPC context that is currently active.
    • Impact: A network switch during owner resolution can allow the previous chain's result to be promoted, while a switch after successful verification leaves the old resolved address trusted without revalidation. Because EVC ownership is chain-local, portfolio positions, activity, locks, rewards, and APY visibility can consequently query or display data for the wrong owner on the newly selected network.
    • Production reachability: credible — Network switching is a normal Lite flow and spy state persists through route and network navigation. The owner-resolution watcher observes the pending candidate, EVC address, and RPC-client reference, but not an explicit chain identity; after pending state is cleared, later chain changes need not invalidate or re-resolve the verified spy address.
    • Evidence: composables/useSpyMode.ts:126-135, composables/useSpyMode.ts:161-170, composables/useSpyMode.ts:67-106, tests/composables/useEffectiveAddress.test.ts:62-128, tests/composables/useSpyMode.test.ts:1-290
    • Recommendation: Bind both request identity and verified spy state to the active chain. Invalidate or re-resolve on every chain change, reject in-flight results from a prior chain, preserve the original candidate if owner rewriting must be repeated, and test both an in-flight chain switch and a switch after successful verification.

Coverage

  • Complete: yes
  • Changed files inventoried: 55
  • components/entities/activity/ActivityAddress.vue: complete
  • components/entities/activity/ActivityCategoryFilters.vue: complete
  • components/entities/activity/ActivityEventRow.vue: complete
  • components/entities/activity/ActivityFeed.vue: complete
  • components/entities/asset/AssetAvatar.vue: complete
  • components/entities/portfolio/PortfolioBorrowItem.vue: complete
  • components/entities/portfolio/PortfolioEarnItem.vue: complete
  • components/entities/portfolio/PortfolioSavingItem.vue: complete
  • components/entities/portfolio/PortfolioUnsupportedBorrowItem.vue: complete
  • components/entities/vault/ChooseCollateralModal.vue: complete
  • components/entities/vault/VaultLabelsAndAssets.vue: complete
  • components/entities/vault/overview/SecuritizeVaultOverview.vue: complete
  • components/entities/vault/overview/VaultOverview.vue: complete
  • components/entities/vault/overview/VaultOverviewAccordionSection.vue: complete
  • components/entities/vault/overview/VaultOverviewBlockActivity.vue: complete
  • components/entities/vault/overview/earn/VaultOverviewEarn.vue: complete
  • components/layout/SpyModeBanner.vue: complete
  • components/ui/UiCustomFilterChips.vue: complete
  • components/ui/UiFilterChip.vue: complete
  • components/ui/UiSelect.vue: complete
  • components/ui/UiTabs.vue: complete
  • composables/useActivityAvailability.ts: complete
  • composables/useActivityFeed.ts: complete
  • composables/useActivityLiquidationDetails.ts: complete
  • composables/useActivityNowMs.ts: complete
  • composables/useApyVisibility.ts: complete
  • composables/useEulerAccount.ts: complete
  • composables/usePortfolioActivityRuntimeSupport.ts: complete
  • composables/useREULLocks.ts: complete
  • composables/useRewardsApy.ts: complete
  • composables/useSpyMode.ts: complete (findings=eprv2-ddff8351d02cb2bb5ac3)
  • middleware/02.spy-param.global.ts: complete
  • package-lock.json: complete
  • pages/portfolio.vue: complete
  • pages/portfolio/activity.vue: complete
  • pages/portfolio/index.vue: complete
  • server/api/internal/v3/[...path].ts: complete
  • server/utils/v3-proxy-backoff.ts: complete
  • server/utils/v3-proxy.ts: complete
  • tests/composables/useActivityAvailability.test.ts: complete
  • tests/composables/useActivityFeed.test.ts: complete
  • tests/composables/useActivityLiquidationDetails.test.ts: complete
  • tests/composables/useActivityNowMs.test.ts: complete
  • tests/composables/useEffectiveAddress.test.ts: complete
  • tests/composables/usePortfolioActivityRuntimeSupport.test.ts: complete
  • tests/composables/useREULLocks.test.ts: complete
  • tests/composables/useRewardsApy.test.ts: complete
  • tests/composables/useSpyMode.test.ts: complete
  • tests/server/v3-proxy-backoff.test.ts: complete
  • tests/server/v3-proxy-route.test.ts: complete
  • tests/server/v3-proxy.test.ts: complete
  • tests/utils/activity-display.test.ts: complete
  • utils/activity-display.ts: complete
  • utils/sdk-query-cache.ts: complete
  • utils/sdk-query-policy.ts: complete

Coverage gaps

  • None.

Validation

@railway-app
railway-app Bot temporarily deployed to euler-lite(dev,PR previews) / euler-lite-pr-736 July 27, 2026 13:49 Destroyed

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

Euler PR review

Reviewed the complete exact-head delta across 55 changed files; no causally attributable findings were retained.

Findings

  • No actionable findings.

Coverage

  • Complete: yes
  • Changed files inventoried: 55
  • components/entities/activity/ActivityAddress.vue: complete
  • components/entities/activity/ActivityCategoryFilters.vue: complete
  • components/entities/activity/ActivityEventRow.vue: complete
  • components/entities/activity/ActivityFeed.vue: complete
  • components/entities/asset/AssetAvatar.vue: complete
  • components/entities/portfolio/PortfolioBorrowItem.vue: complete
  • components/entities/portfolio/PortfolioEarnItem.vue: complete
  • components/entities/portfolio/PortfolioSavingItem.vue: complete
  • components/entities/portfolio/PortfolioUnsupportedBorrowItem.vue: complete
  • components/entities/vault/ChooseCollateralModal.vue: complete
  • components/entities/vault/VaultLabelsAndAssets.vue: complete
  • components/entities/vault/overview/SecuritizeVaultOverview.vue: complete
  • components/entities/vault/overview/VaultOverview.vue: complete
  • components/entities/vault/overview/VaultOverviewAccordionSection.vue: complete
  • components/entities/vault/overview/VaultOverviewBlockActivity.vue: complete
  • components/entities/vault/overview/earn/VaultOverviewEarn.vue: complete
  • components/layout/SpyModeBanner.vue: complete
  • components/ui/UiCustomFilterChips.vue: complete
  • components/ui/UiFilterChip.vue: complete
  • components/ui/UiSelect.vue: complete
  • components/ui/UiTabs.vue: complete
  • composables/useActivityAvailability.ts: complete
  • composables/useActivityFeed.ts: complete
  • composables/useActivityLiquidationDetails.ts: complete
  • composables/useActivityNowMs.ts: complete
  • composables/useApyVisibility.ts: complete
  • composables/useEulerAccount.ts: complete
  • composables/usePortfolioActivityRuntimeSupport.ts: complete
  • composables/useREULLocks.ts: complete
  • composables/useRewardsApy.ts: complete
  • composables/useSpyMode.ts: complete
  • middleware/02.spy-param.global.ts: complete
  • package-lock.json: complete
  • pages/portfolio.vue: complete
  • pages/portfolio/activity.vue: complete
  • pages/portfolio/index.vue: complete
  • server/api/internal/v3/[...path].ts: complete
  • server/utils/v3-proxy-backoff.ts: complete
  • server/utils/v3-proxy.ts: complete
  • tests/composables/useActivityAvailability.test.ts: complete
  • tests/composables/useActivityFeed.test.ts: complete
  • tests/composables/useActivityLiquidationDetails.test.ts: complete
  • tests/composables/useActivityNowMs.test.ts: complete
  • tests/composables/useEffectiveAddress.test.ts: complete
  • tests/composables/usePortfolioActivityRuntimeSupport.test.ts: complete
  • tests/composables/useREULLocks.test.ts: complete
  • tests/composables/useRewardsApy.test.ts: complete
  • tests/composables/useSpyMode.test.ts: complete
  • tests/server/v3-proxy-backoff.test.ts: complete
  • tests/server/v3-proxy-route.test.ts: complete
  • tests/server/v3-proxy.test.ts: complete
  • tests/utils/activity-display.test.ts: complete
  • utils/activity-display.ts: complete
  • utils/sdk-query-cache.ts: complete
  • utils/sdk-query-policy.ts: complete

Coverage gaps

  • None.

Validation

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

Euler PR review

Reviewed the complete exact-head delta across 55 changed files; no causally attributable findings were retained.

Findings

  • No actionable findings.

Coverage

  • Complete: yes
  • Changed files inventoried: 55
  • components/entities/activity/ActivityAddress.vue: complete
  • components/entities/activity/ActivityCategoryFilters.vue: complete
  • components/entities/activity/ActivityEventRow.vue: complete
  • components/entities/activity/ActivityFeed.vue: complete
  • components/entities/asset/AssetAvatar.vue: complete
  • components/entities/portfolio/PortfolioBorrowItem.vue: complete
  • components/entities/portfolio/PortfolioEarnItem.vue: complete
  • components/entities/portfolio/PortfolioSavingItem.vue: complete
  • components/entities/portfolio/PortfolioUnsupportedBorrowItem.vue: complete
  • components/entities/vault/ChooseCollateralModal.vue: complete
  • components/entities/vault/VaultLabelsAndAssets.vue: complete
  • components/entities/vault/overview/SecuritizeVaultOverview.vue: complete
  • components/entities/vault/overview/VaultOverview.vue: complete
  • components/entities/vault/overview/VaultOverviewAccordionSection.vue: complete
  • components/entities/vault/overview/VaultOverviewBlockActivity.vue: complete
  • components/entities/vault/overview/earn/VaultOverviewEarn.vue: complete
  • components/layout/SpyModeBanner.vue: complete
  • components/ui/UiCustomFilterChips.vue: complete
  • components/ui/UiFilterChip.vue: complete
  • components/ui/UiSelect.vue: complete
  • components/ui/UiTabs.vue: complete
  • composables/useActivityAvailability.ts: complete
  • composables/useActivityFeed.ts: complete
  • composables/useActivityLiquidationDetails.ts: complete
  • composables/useActivityNowMs.ts: complete
  • composables/useApyVisibility.ts: complete
  • composables/useEulerAccount.ts: complete
  • composables/usePortfolioActivityRuntimeSupport.ts: complete
  • composables/useREULLocks.ts: complete
  • composables/useRewardsApy.ts: complete
  • composables/useSpyMode.ts: complete
  • middleware/02.spy-param.global.ts: complete
  • package-lock.json: complete
  • pages/portfolio.vue: complete
  • pages/portfolio/activity.vue: complete
  • pages/portfolio/index.vue: complete
  • server/api/internal/v3/[...path].ts: complete
  • server/utils/v3-proxy-backoff.ts: complete
  • server/utils/v3-proxy.ts: complete
  • tests/composables/useActivityAvailability.test.ts: complete
  • tests/composables/useActivityFeed.test.ts: complete
  • tests/composables/useActivityLiquidationDetails.test.ts: complete
  • tests/composables/useActivityNowMs.test.ts: complete
  • tests/composables/useEffectiveAddress.test.ts: complete
  • tests/composables/usePortfolioActivityRuntimeSupport.test.ts: complete
  • tests/composables/useREULLocks.test.ts: complete
  • tests/composables/useRewardsApy.test.ts: complete
  • tests/composables/useSpyMode.test.ts: complete
  • tests/server/v3-proxy-backoff.test.ts: complete
  • tests/server/v3-proxy-route.test.ts: complete
  • tests/server/v3-proxy.test.ts: complete
  • tests/utils/activity-display.test.ts: complete
  • utils/activity-display.ts: complete
  • utils/sdk-query-cache.ts: complete
  • utils/sdk-query-policy.ts: complete

Coverage gaps

  • None.

Validation

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

Euler PR review

Reviewed the complete exact-head delta across 55 changed files; no causally attributable findings were retained.

Findings

  • No actionable findings.

Coverage

  • Complete: yes
  • Changed files inventoried: 55
  • components/entities/activity/ActivityAddress.vue: complete
  • components/entities/activity/ActivityCategoryFilters.vue: complete
  • components/entities/activity/ActivityEventRow.vue: complete
  • components/entities/activity/ActivityFeed.vue: complete
  • components/entities/asset/AssetAvatar.vue: complete
  • components/entities/portfolio/PortfolioBorrowItem.vue: complete
  • components/entities/portfolio/PortfolioEarnItem.vue: complete
  • components/entities/portfolio/PortfolioSavingItem.vue: complete
  • components/entities/portfolio/PortfolioUnsupportedBorrowItem.vue: complete
  • components/entities/vault/ChooseCollateralModal.vue: complete
  • components/entities/vault/VaultLabelsAndAssets.vue: complete
  • components/entities/vault/overview/SecuritizeVaultOverview.vue: complete
  • components/entities/vault/overview/VaultOverview.vue: complete
  • components/entities/vault/overview/VaultOverviewAccordionSection.vue: complete
  • components/entities/vault/overview/VaultOverviewBlockActivity.vue: complete
  • components/entities/vault/overview/earn/VaultOverviewEarn.vue: complete
  • components/layout/SpyModeBanner.vue: complete
  • components/ui/UiCustomFilterChips.vue: complete
  • components/ui/UiFilterChip.vue: complete
  • components/ui/UiSelect.vue: complete
  • components/ui/UiTabs.vue: complete
  • composables/useActivityAvailability.ts: complete
  • composables/useActivityFeed.ts: complete
  • composables/useActivityLiquidationDetails.ts: complete
  • composables/useActivityNowMs.ts: complete
  • composables/useApyVisibility.ts: complete
  • composables/useEulerAccount.ts: complete
  • composables/usePortfolioActivityRuntimeSupport.ts: complete
  • composables/useREULLocks.ts: complete
  • composables/useRewardsApy.ts: complete
  • composables/useSpyMode.ts: complete
  • middleware/02.spy-param.global.ts: complete
  • package-lock.json: complete
  • pages/portfolio.vue: complete
  • pages/portfolio/activity.vue: complete
  • pages/portfolio/index.vue: complete
  • server/api/internal/v3/[...path].ts: complete
  • server/utils/v3-proxy-backoff.ts: complete
  • server/utils/v3-proxy.ts: complete
  • tests/composables/useActivityAvailability.test.ts: complete
  • tests/composables/useActivityFeed.test.ts: complete
  • tests/composables/useActivityLiquidationDetails.test.ts: complete
  • tests/composables/useActivityNowMs.test.ts: complete
  • tests/composables/useEffectiveAddress.test.ts: complete
  • tests/composables/usePortfolioActivityRuntimeSupport.test.ts: complete
  • tests/composables/useREULLocks.test.ts: complete
  • tests/composables/useRewardsApy.test.ts: complete
  • tests/composables/useSpyMode.test.ts: complete
  • tests/server/v3-proxy-backoff.test.ts: complete
  • tests/server/v3-proxy-route.test.ts: complete
  • tests/server/v3-proxy.test.ts: complete
  • tests/utils/activity-display.test.ts: complete
  • utils/activity-display.ts: complete
  • utils/sdk-query-cache.ts: complete
  • utils/sdk-query-policy.ts: complete

Coverage gaps

  • None.

Validation

Seranged added 4 commits July 28, 2026 17:37
- render historical liquidation valuation fallbacks through the shared row formatter
- decode vault and hooked-operation details with compact responsive disclosure styling
- align portfolio empty, loading, timestamp, and transfer presentation
- compact token quantities and render unlimited caps semantically
- collapse multi-strategy queue details behind an expandable summary
- keep the final pagination action centered within the feed
# Conflicts:
#	package-lock.json
#	package.json
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.

3 participants