Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds 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. ChangesActivity feed and vault integration
V3 activity proxy support
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
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
🚅 Deployed to the euler-lite-pr-736 environment in euler-lite(dev,PR previews)
|
- keep historical EVK categories independent of current borrowability - distinguish partial coverage and bound proxy backoffs
There was a problem hiding this comment.
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
📒 Files selected for processing (22)
components/entities/activity/ActivityCategoryFilters.vuecomponents/entities/activity/ActivityEventRow.vuecomponents/entities/activity/ActivityFeed.vuecomponents/entities/vault/overview/SecuritizeVaultOverview.vuecomponents/entities/vault/overview/VaultOverview.vuecomponents/entities/vault/overview/VaultOverviewAccordionSection.vuecomponents/entities/vault/overview/VaultOverviewBlockActivity.vuecomponents/entities/vault/overview/earn/VaultOverviewEarn.vuecomposables/useActivityAvailability.tscomposables/useActivityFeed.tsserver/api/internal/v3/[...path].tsserver/utils/v3-proxy-backoff.tsserver/utils/v3-proxy.tstests/composables/useActivityAvailability.test.tstests/composables/useActivityFeed.test.tstests/server/v3-proxy-backoff.test.tstests/server/v3-proxy-route.test.tstests/server/v3-proxy.test.tstests/utils/activity-display.test.tsutils/activity-display.tsutils/sdk-query-cache.tsutils/sdk-query-policy.ts
Keep raw V3 activity available while Lite requests only scope-relevant display events and suppresses accrual and paired share-movement noise.
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
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 typecheckfails 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.tsbecause 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 andLoad olderincreased 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:
Mobile — 390×844 vault information modal with the open Activity section and horizontally scrollable filters:
- 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
There was a problem hiding this comment.
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
📒 Files selected for processing (7)
components/entities/activity/ActivityAddress.vuecomponents/entities/activity/ActivityEventRow.vuecomponents/entities/activity/ActivityFeed.vuecomposables/useActivityFeed.tstests/composables/useActivityFeed.test.tstests/utils/activity-display.test.tsutils/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
Show historical amounts in underlying asset units and conservatively collapse exact paired operations.
Use the available Activity feed width to switch between compact and full table layouts, keeping vault rows readable without changing the wider portfolio presentation.
Group participant metadata with the event summary at constrained feed widths so vault activity stays dense while preserving the wide portfolio table.
Emphasize event amounts, reduce redundant asset labels, and present expandable metadata as a compact accessible disclosure control.
- 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.
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
Reviewed current head 2e5bbe4b4b726c9536d0478491a78e8640d95e7b.
Requesting changes for two blocking issues:
- The pinned
@eulerxyz/euler-v2-sdk@1.2.0does not exportLiquidationRecord,activityService.fetchLiquidations, orqueryLiquidations. 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. - Pending spy-owner verification is not fail-closed across sibling consumers.
useEulerAccount,useRewardsApy,useApyVisibility, anduseREULLockscan fall back to the connected wallet while spy mode is active butspyAddressis 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
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.
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
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
LiquidationRecordimport sites,fetchLiquidations, and thequeryLiquidationspolicy row. - The full suite reports 1 failed / 1,322 passed because
queryLiquidationswas 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
Mobile 390×844 — selected Liquidations filter and event card
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
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
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)
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
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.
- Files:
- [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.
- Files:
- [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.
- Files:
- [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.
- Files:
- [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.
- Files:
- [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.
- Files:
Coverage
- Complete: yes
- Changed files inventoried: 55
components/entities/activity/ActivityAddress.vue: completecomponents/entities/activity/ActivityCategoryFilters.vue: completecomponents/entities/activity/ActivityEventRow.vue: complete (findings=eprv2-43e8a25b0fece6e78053)components/entities/activity/ActivityFeed.vue: complete (findings=eprv2-43e8a25b0fece6e78053)components/entities/asset/AssetAvatar.vue: completecomponents/entities/portfolio/PortfolioBorrowItem.vue: completecomponents/entities/portfolio/PortfolioEarnItem.vue: completecomponents/entities/portfolio/PortfolioSavingItem.vue: completecomponents/entities/portfolio/PortfolioUnsupportedBorrowItem.vue: completecomponents/entities/vault/ChooseCollateralModal.vue: completecomponents/entities/vault/VaultLabelsAndAssets.vue: completecomponents/entities/vault/overview/SecuritizeVaultOverview.vue: completecomponents/entities/vault/overview/VaultOverview.vue: completecomponents/entities/vault/overview/VaultOverviewAccordionSection.vue: completecomponents/entities/vault/overview/VaultOverviewBlockActivity.vue: completecomponents/entities/vault/overview/earn/VaultOverviewEarn.vue: completecomponents/layout/SpyModeBanner.vue: complete (findings=eprv2-c78e8c8767b0a565b22f)components/ui/UiCustomFilterChips.vue: completecomponents/ui/UiFilterChip.vue: completecomponents/ui/UiSelect.vue: completecomponents/ui/UiTabs.vue: completecomposables/useActivityAvailability.ts: completecomposables/useActivityFeed.ts: completecomposables/useActivityLiquidationDetails.ts: complete (findings=eprv2-07afa7a2ea65e6e45959,eprv2-43e8a25b0fece6e78053,eprv2-85c40cb34385a1b59ccf)composables/useActivityNowMs.ts: completecomposables/useApyVisibility.ts: completecomposables/useEulerAccount.ts: completecomposables/usePortfolioActivityRuntimeSupport.ts: completecomposables/useREULLocks.ts: completecomposables/useRewardsApy.ts: completecomposables/useSpyMode.ts: complete (findings=eprv2-86efd4cb890a0bbf8770,eprv2-c78e8c8767b0a565b22f)middleware/02.spy-param.global.ts: completepackage-lock.json: complete (findings=eprv2-43e8a25b0fece6e78053)pages/portfolio.vue: completepages/portfolio/activity.vue: completepages/portfolio/index.vue: completeserver/api/internal/v3/[...path].ts: completeserver/utils/v3-proxy-backoff.ts: complete (findings=eprv2-846cfb17c62fb7747bb0)server/utils/v3-proxy.ts: completetests/composables/useActivityAvailability.test.ts: completetests/composables/useActivityFeed.test.ts: completetests/composables/useActivityLiquidationDetails.test.ts: complete (findings=eprv2-07afa7a2ea65e6e45959,eprv2-43e8a25b0fece6e78053,eprv2-85c40cb34385a1b59ccf)tests/composables/useActivityNowMs.test.ts: completetests/composables/useEffectiveAddress.test.ts: complete (findings=eprv2-86efd4cb890a0bbf8770)tests/composables/usePortfolioActivityRuntimeSupport.test.ts: completetests/composables/useREULLocks.test.ts: completetests/composables/useRewardsApy.test.ts: completetests/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: completetests/server/v3-proxy.test.ts: completetests/utils/activity-display.test.ts: completeutils/activity-display.ts: completeutils/sdk-query-cache.ts: completeutils/sdk-query-policy.ts: complete (findings=eprv2-85c40cb34385a1b59ccf)
Coverage gaps
- None.
Validation
- exact-base CI sufficiency: passed — 4 passed; 0 failed; 0 pending; 4 total
- exact-base CI: Dependabot: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30239222337/job/89892786230
- exact-base CI: lint: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483281053
- exact-base CI: test: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483281029
- exact-base CI: typecheck: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483280963
- exact-head CI sufficiency: failed — 1 passed; 2 failed; 0 pending; 3 total
- exact-head CI: lint: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30258585778/job/89952896611
- exact-head CI: test: failed — https://github.com/euler-xyz/euler-lite/actions/runs/30258585778/job/89952896400
- exact-head CI: typecheck: failed — https://github.com/euler-xyz/euler-lite/actions/runs/30258585778/job/89952896728
- parent exact-delta git diff --check: passed — git diff --check: clean
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
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.
- Files:
Coverage
- Complete: yes
- Changed files inventoried: 55
components/entities/activity/ActivityAddress.vue: completecomponents/entities/activity/ActivityCategoryFilters.vue: completecomponents/entities/activity/ActivityEventRow.vue: completecomponents/entities/activity/ActivityFeed.vue: completecomponents/entities/asset/AssetAvatar.vue: completecomponents/entities/portfolio/PortfolioBorrowItem.vue: completecomponents/entities/portfolio/PortfolioEarnItem.vue: completecomponents/entities/portfolio/PortfolioSavingItem.vue: completecomponents/entities/portfolio/PortfolioUnsupportedBorrowItem.vue: completecomponents/entities/vault/ChooseCollateralModal.vue: completecomponents/entities/vault/VaultLabelsAndAssets.vue: completecomponents/entities/vault/overview/SecuritizeVaultOverview.vue: completecomponents/entities/vault/overview/VaultOverview.vue: completecomponents/entities/vault/overview/VaultOverviewAccordionSection.vue: completecomponents/entities/vault/overview/VaultOverviewBlockActivity.vue: completecomponents/entities/vault/overview/earn/VaultOverviewEarn.vue: completecomponents/layout/SpyModeBanner.vue: completecomponents/ui/UiCustomFilterChips.vue: completecomponents/ui/UiFilterChip.vue: completecomponents/ui/UiSelect.vue: completecomponents/ui/UiTabs.vue: completecomposables/useActivityAvailability.ts: completecomposables/useActivityFeed.ts: completecomposables/useActivityLiquidationDetails.ts: completecomposables/useActivityNowMs.ts: completecomposables/useApyVisibility.ts: completecomposables/useEulerAccount.ts: completecomposables/usePortfolioActivityRuntimeSupport.ts: completecomposables/useREULLocks.ts: completecomposables/useRewardsApy.ts: completecomposables/useSpyMode.ts: complete (findings=eprv2-ddff8351d02cb2bb5ac3)middleware/02.spy-param.global.ts: completepackage-lock.json: completepages/portfolio.vue: completepages/portfolio/activity.vue: completepages/portfolio/index.vue: completeserver/api/internal/v3/[...path].ts: completeserver/utils/v3-proxy-backoff.ts: completeserver/utils/v3-proxy.ts: completetests/composables/useActivityAvailability.test.ts: completetests/composables/useActivityFeed.test.ts: completetests/composables/useActivityLiquidationDetails.test.ts: completetests/composables/useActivityNowMs.test.ts: completetests/composables/useEffectiveAddress.test.ts: completetests/composables/usePortfolioActivityRuntimeSupport.test.ts: completetests/composables/useREULLocks.test.ts: completetests/composables/useRewardsApy.test.ts: completetests/composables/useSpyMode.test.ts: completetests/server/v3-proxy-backoff.test.ts: completetests/server/v3-proxy-route.test.ts: completetests/server/v3-proxy.test.ts: completetests/utils/activity-display.test.ts: completeutils/activity-display.ts: completeutils/sdk-query-cache.ts: completeutils/sdk-query-policy.ts: complete
Coverage gaps
- None.
Validation
- exact-base CI sufficiency: passed — 5 passed; 0 failed; 0 pending; 5 total
- exact-base CI: audit: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30265701687/job/89975733936
- exact-base CI: Dependabot: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30239222337/job/89892786230
- exact-base CI: lint: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483281053
- exact-base CI: test: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483281029
- exact-base CI: typecheck: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483280963
- exact-head CI sufficiency: failed — 1 passed; 2 failed; 0 pending; 3 total
- exact-head CI: lint: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30269211629/job/89987289554
- exact-head CI: test: failed — https://github.com/euler-xyz/euler-lite/actions/runs/30269211629/job/89987289415
- exact-head CI: typecheck: failed — https://github.com/euler-xyz/euler-lite/actions/runs/30269211629/job/89987289981
- parent exact-delta git diff --check: passed — git diff --check: clean
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
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: completecomponents/entities/activity/ActivityCategoryFilters.vue: completecomponents/entities/activity/ActivityEventRow.vue: completecomponents/entities/activity/ActivityFeed.vue: completecomponents/entities/asset/AssetAvatar.vue: completecomponents/entities/portfolio/PortfolioBorrowItem.vue: completecomponents/entities/portfolio/PortfolioEarnItem.vue: completecomponents/entities/portfolio/PortfolioSavingItem.vue: completecomponents/entities/portfolio/PortfolioUnsupportedBorrowItem.vue: completecomponents/entities/vault/ChooseCollateralModal.vue: completecomponents/entities/vault/VaultLabelsAndAssets.vue: completecomponents/entities/vault/overview/SecuritizeVaultOverview.vue: completecomponents/entities/vault/overview/VaultOverview.vue: completecomponents/entities/vault/overview/VaultOverviewAccordionSection.vue: completecomponents/entities/vault/overview/VaultOverviewBlockActivity.vue: completecomponents/entities/vault/overview/earn/VaultOverviewEarn.vue: completecomponents/layout/SpyModeBanner.vue: completecomponents/ui/UiCustomFilterChips.vue: completecomponents/ui/UiFilterChip.vue: completecomponents/ui/UiSelect.vue: completecomponents/ui/UiTabs.vue: completecomposables/useActivityAvailability.ts: completecomposables/useActivityFeed.ts: completecomposables/useActivityLiquidationDetails.ts: completecomposables/useActivityNowMs.ts: completecomposables/useApyVisibility.ts: completecomposables/useEulerAccount.ts: completecomposables/usePortfolioActivityRuntimeSupport.ts: completecomposables/useREULLocks.ts: completecomposables/useRewardsApy.ts: completecomposables/useSpyMode.ts: completemiddleware/02.spy-param.global.ts: completepackage-lock.json: completepages/portfolio.vue: completepages/portfolio/activity.vue: completepages/portfolio/index.vue: completeserver/api/internal/v3/[...path].ts: completeserver/utils/v3-proxy-backoff.ts: completeserver/utils/v3-proxy.ts: completetests/composables/useActivityAvailability.test.ts: completetests/composables/useActivityFeed.test.ts: completetests/composables/useActivityLiquidationDetails.test.ts: completetests/composables/useActivityNowMs.test.ts: completetests/composables/useEffectiveAddress.test.ts: completetests/composables/usePortfolioActivityRuntimeSupport.test.ts: completetests/composables/useREULLocks.test.ts: completetests/composables/useRewardsApy.test.ts: completetests/composables/useSpyMode.test.ts: completetests/server/v3-proxy-backoff.test.ts: completetests/server/v3-proxy-route.test.ts: completetests/server/v3-proxy.test.ts: completetests/utils/activity-display.test.ts: completeutils/activity-display.ts: completeutils/sdk-query-cache.ts: completeutils/sdk-query-policy.ts: complete
Coverage gaps
- None.
Validation
- exact-base CI sufficiency: passed — 5 passed; 0 failed; 0 pending; 5 total
- exact-base CI: audit: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30265701687/job/89975733936
- exact-base CI: Dependabot: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30239222337/job/89892786230
- exact-base CI: lint: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483281053
- exact-base CI: test: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483281029
- exact-base CI: typecheck: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483280963
- exact-head CI sufficiency: failed — 1 passed; 2 failed; 0 pending; 3 total
- exact-head CI: lint: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30272114500/job/89996977239
- exact-head CI: test: failed — https://github.com/euler-xyz/euler-lite/actions/runs/30272114500/job/89996977286
- exact-head CI: typecheck: failed — https://github.com/euler-xyz/euler-lite/actions/runs/30272114500/job/89996977292
- parent exact-delta git diff --check: passed — git diff --check: clean
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
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: completecomponents/entities/activity/ActivityCategoryFilters.vue: completecomponents/entities/activity/ActivityEventRow.vue: completecomponents/entities/activity/ActivityFeed.vue: completecomponents/entities/asset/AssetAvatar.vue: completecomponents/entities/portfolio/PortfolioBorrowItem.vue: completecomponents/entities/portfolio/PortfolioEarnItem.vue: completecomponents/entities/portfolio/PortfolioSavingItem.vue: completecomponents/entities/portfolio/PortfolioUnsupportedBorrowItem.vue: completecomponents/entities/vault/ChooseCollateralModal.vue: completecomponents/entities/vault/VaultLabelsAndAssets.vue: completecomponents/entities/vault/overview/SecuritizeVaultOverview.vue: completecomponents/entities/vault/overview/VaultOverview.vue: completecomponents/entities/vault/overview/VaultOverviewAccordionSection.vue: completecomponents/entities/vault/overview/VaultOverviewBlockActivity.vue: completecomponents/entities/vault/overview/earn/VaultOverviewEarn.vue: completecomponents/layout/SpyModeBanner.vue: completecomponents/ui/UiCustomFilterChips.vue: completecomponents/ui/UiFilterChip.vue: completecomponents/ui/UiSelect.vue: completecomponents/ui/UiTabs.vue: completecomposables/useActivityAvailability.ts: completecomposables/useActivityFeed.ts: completecomposables/useActivityLiquidationDetails.ts: completecomposables/useActivityNowMs.ts: completecomposables/useApyVisibility.ts: completecomposables/useEulerAccount.ts: completecomposables/usePortfolioActivityRuntimeSupport.ts: completecomposables/useREULLocks.ts: completecomposables/useRewardsApy.ts: completecomposables/useSpyMode.ts: completemiddleware/02.spy-param.global.ts: completepackage-lock.json: completepages/portfolio.vue: completepages/portfolio/activity.vue: completepages/portfolio/index.vue: completeserver/api/internal/v3/[...path].ts: completeserver/utils/v3-proxy-backoff.ts: completeserver/utils/v3-proxy.ts: completetests/composables/useActivityAvailability.test.ts: completetests/composables/useActivityFeed.test.ts: completetests/composables/useActivityLiquidationDetails.test.ts: completetests/composables/useActivityNowMs.test.ts: completetests/composables/useEffectiveAddress.test.ts: completetests/composables/usePortfolioActivityRuntimeSupport.test.ts: completetests/composables/useREULLocks.test.ts: completetests/composables/useRewardsApy.test.ts: completetests/composables/useSpyMode.test.ts: completetests/server/v3-proxy-backoff.test.ts: completetests/server/v3-proxy-route.test.ts: completetests/server/v3-proxy.test.ts: completetests/utils/activity-display.test.ts: completeutils/activity-display.ts: completeutils/sdk-query-cache.ts: completeutils/sdk-query-policy.ts: complete
Coverage gaps
- None.
Validation
- exact-base CI sufficiency: passed — 5 passed; 0 failed; 0 pending; 5 total
- exact-base CI: audit: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30265701687/job/89975733936
- exact-base CI: Dependabot: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30239222337/job/89892786230
- exact-base CI: lint: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483281053
- exact-base CI: test: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483281029
- exact-base CI: typecheck: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483280963
- exact-head CI sufficiency: failed — 1 passed; 2 failed; 0 pending; 3 total
- exact-head CI: lint: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30272783556/job/89999220025
- exact-head CI: test: failed — https://github.com/euler-xyz/euler-lite/actions/runs/30272783556/job/89999219853
- exact-head CI: typecheck: failed — https://github.com/euler-xyz/euler-lite/actions/runs/30272783556/job/89999220027
- parent exact-delta git diff --check: passed — git diff --check: clean
LeonardEulerXYZ
left a comment
There was a problem hiding this comment.
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: completecomponents/entities/activity/ActivityCategoryFilters.vue: completecomponents/entities/activity/ActivityEventRow.vue: completecomponents/entities/activity/ActivityFeed.vue: completecomponents/entities/asset/AssetAvatar.vue: completecomponents/entities/portfolio/PortfolioBorrowItem.vue: completecomponents/entities/portfolio/PortfolioEarnItem.vue: completecomponents/entities/portfolio/PortfolioSavingItem.vue: completecomponents/entities/portfolio/PortfolioUnsupportedBorrowItem.vue: completecomponents/entities/vault/ChooseCollateralModal.vue: completecomponents/entities/vault/VaultLabelsAndAssets.vue: completecomponents/entities/vault/overview/SecuritizeVaultOverview.vue: completecomponents/entities/vault/overview/VaultOverview.vue: completecomponents/entities/vault/overview/VaultOverviewAccordionSection.vue: completecomponents/entities/vault/overview/VaultOverviewBlockActivity.vue: completecomponents/entities/vault/overview/earn/VaultOverviewEarn.vue: completecomponents/layout/SpyModeBanner.vue: completecomponents/ui/UiCustomFilterChips.vue: completecomponents/ui/UiFilterChip.vue: completecomponents/ui/UiSelect.vue: completecomponents/ui/UiTabs.vue: completecomposables/useActivityAvailability.ts: completecomposables/useActivityFeed.ts: completecomposables/useActivityLiquidationDetails.ts: completecomposables/useActivityNowMs.ts: completecomposables/useApyVisibility.ts: completecomposables/useEulerAccount.ts: completecomposables/usePortfolioActivityRuntimeSupport.ts: completecomposables/useREULLocks.ts: completecomposables/useRewardsApy.ts: completecomposables/useSpyMode.ts: completemiddleware/02.spy-param.global.ts: completepackage-lock.json: completepages/portfolio.vue: completepages/portfolio/activity.vue: completepages/portfolio/index.vue: completeserver/api/internal/v3/[...path].ts: completeserver/utils/v3-proxy-backoff.ts: completeserver/utils/v3-proxy.ts: completetests/composables/useActivityAvailability.test.ts: completetests/composables/useActivityFeed.test.ts: completetests/composables/useActivityLiquidationDetails.test.ts: completetests/composables/useActivityNowMs.test.ts: completetests/composables/useEffectiveAddress.test.ts: completetests/composables/usePortfolioActivityRuntimeSupport.test.ts: completetests/composables/useREULLocks.test.ts: completetests/composables/useRewardsApy.test.ts: completetests/composables/useSpyMode.test.ts: completetests/server/v3-proxy-backoff.test.ts: completetests/server/v3-proxy-route.test.ts: completetests/server/v3-proxy.test.ts: completetests/utils/activity-display.test.ts: completeutils/activity-display.ts: completeutils/sdk-query-cache.ts: completeutils/sdk-query-policy.ts: complete
Coverage gaps
- None.
Validation
- exact-base CI sufficiency: passed — 5 passed; 0 failed; 0 pending; 5 total
- exact-base CI: audit: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30265701687/job/89975733936
- exact-base CI: Dependabot: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30239222337/job/89892786230
- exact-base CI: lint: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483281053
- exact-base CI: test: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483281029
- exact-base CI: typecheck: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30093907539/job/89483280963
- exact-head CI sufficiency: failed — 1 passed; 2 failed; 0 pending; 3 total
- exact-head CI: lint: passed — https://github.com/euler-xyz/euler-lite/actions/runs/30277232500/job/90014261875
- exact-head CI: test: failed — https://github.com/euler-xyz/euler-lite/actions/runs/30277232500/job/90014261951
- exact-head CI: typecheck: failed — https://github.com/euler-xyz/euler-lite/actions/runs/30277232500/job/90014262199
- parent exact-delta git diff --check: passed — git diff --check: clean
- 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






Summary
UX and presentation
Availability and data integrity
Test plan
@eulerxyz/euler-v2-sdk@1.2.0and pass the full test, typecheck, and production-build gates