Skip to content

feat: soft launch#249

Merged
antoncoding merged 20 commits intomasterfrom
feat/autovault
Dec 24, 2025
Merged

feat: soft launch#249
antoncoding merged 20 commits intomasterfrom
feat/autovault

Conversation

@antoncoding
Copy link
Owner

@antoncoding antoncoding commented Dec 23, 2025

  • no navbar
  • abdicate for morpho registry

Summary by CodeRabbit

  • New Features

    • Transaction history preview and grouped history view with rebalance/detail drilldowns
    • Vault indexing helpers and a hook to track indexing progress with toasts
    • Deployment flow: success confirmation and quick "navigate to vault" action
  • Improvements

    • Streamlined vault initialization with metadata step and setup-state gating across detail pages
    • Updated allocation/collateral/allocator cards with previews, skeletons, and improved empty states
    • Token selection suggests USDC-on-Base
  • Removed

    • Autovault entry from main navigation
    • Vault-existence checks from deployment flow

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Contributor

vercel bot commented Dec 23, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
monarch Ready Ready Preview, Comment Dec 24, 2025 0:59am

@coderabbitai
Copy link

coderabbitai bot commented Dec 23, 2025

📝 Walkthrough

Walkthrough

Adds per-address vault fetching, deployment phases with address capture and navigation, vault indexing with polling/toasts, transaction grouping and history preview, initialization metadata step (name/symbol), and broad UI/state refactors across autovault list/detail, allocation tables, and history components.

Changes

Cohort / File(s) Summary
Navbar
src/components/layout/header/Navbar.tsx, src/components/layout/header/NavbarMobile.tsx
Autovault menu item commented out in both desktop and mobile navs (UI comment-only change).
Morpho API v2 Vaults
src/data-sources/morpho-api/v2-vaults.ts, src/graphql/morpho-api-queries.ts
Switched to single-address GraphQL query (vaultV2ByAddress), removed totalSupply from types/transform, changed fetch from batched to per-address calls with per-address error/null handling.
GraphQL / Fetchers / Subgraph
src/graphql/morpho-v2-subgraph-queries.ts, src/data-sources/morpho-api/fetchers.ts, src/data-sources/subgraph/v2-vaults.ts
Query formatting and shape updates; added cache: 'no-store' to fetcher; removed runtime console.logs.
Deployment Context
src/features/autovault/components/deployment/deployment-context.tsx
Introduced DeploymentPhase type, deployedVaultAddress, navigateToVault; await tx receipt, decode CreateVaultV2 event, persist deployed address (local + optional storage), and drive phase transitions.
Deployment UI
src/features/autovault/components/deployment/deployment-modal.tsx, src/features/autovault/components/deployment/token-selection.tsx
Removed existingVaults prop and vault-existence UI; simplified deploy button logic; token selection now suggests USDC-on-Base and drops vault-related flags/UI.
Vault Initialization
src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx, src/hooks/useVaultV2.ts, src/hooks/useVaultV2Data.ts
Replaced adapter-cap step with metadata (name/symbol) step; deployment now awaits receipt and decodes adapter events; completeInitialization signature extended; removed totalSupply from data types.
Vault List & Detail Views
src/features/autovault/vault-list-view.tsx, src/features/autovault/vault-view.tsx, src/hooks/useVaultPage.ts
List view: fetches addresses across networks, merges with local deployed vaults, shows skeleton/benefits UI. Detail view: added indexing gating (useVaultIndexing), switched gating to needsInitialization, threaded isLoading/isInitializing flags.
Indexing & Storage Utilities
src/utils/vault-indexing.ts, src/hooks/useVaultIndexing.tsx, src/utils/vault-storage.ts
New vault indexing localStorage schema and helpers (start/get/stop); hook polls indexing state, shows toasts, retries refetch, and clears on success/timeout; persistent per-owner deployed-vault storage utilities added.
Create / Deploy Hooks
src/hooks/useCreateVault.ts, src/hooks/useDeployMorphoMarketV1Adapter.ts
createVault and deploy hooks now return tx hash (0x...) or undefined on early exit/errors (previously returned void).
Allocation / Caps / Cards
src/features/autovault/components/vault-detail/settings/EditCaps.tsx, src/features/autovault/components/vault-detail/vault-allocator-card.tsx, src/features/autovault/components/vault-detail/vault-collaterals-card.tsx, src/features/autovault/components/vault-detail/vault-market-allocations.tsx, src/features/autovault/components/vault-detail/allocations/.../*, src/features/autovault/components/vault-detail/total-supply-card.tsx
Conditional adapter-cap updates (only patch when needed); removed early-returns for setup states and added setup-required UI branch; preview+tooltip for overflow items; allocation tables simplified to use AllocationCell; TotalSupplyCard gains isLoading prop and skeleton UI.
History & Transaction Grouping
src/features/history/components/history-table.tsx, src/features/history/components/rebalance-detail.tsx, src/features/history/components/transaction-history-preview.tsx, src/features/history/history-view.tsx, src/utils/transactionGrouping.ts, src/utils/storageKeys.ts
New transaction grouping utilities (group by tx hash, detect rebalance/deposits/withdrawals), grouped/un-grouped history UI, settings modal (pageSize/grouped view), RebalanceDetail and TransactionHistoryPreview components, added storage keys for persistence.
Markets / Onboarding
src/features/markets/components/markets-table-same-loan.tsx, src/features/positions/components/onboarding/market-selection-onboarding.tsx
Removed cart/staging UI and showCart prop; adjusted internal selection naming.
Common UI Container
src/components/common/table-container-with-header.tsx
Added TableContainerWithDescription component supporting title, description, and actions.
Misc Utilities
src/utils/monarch-agent.ts, src/components/layout/header/Navbar.tsx
Removed getAgentContract, updated Max APY agent description string; minor navbar comment formatting.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant DeployModal as Deployment Modal
    participant DeployCtx as Deployment Context
    participant RPC as Blockchain (publicClient/contract)
    participant Router as Router
    participant Storage as LocalStorage

    User->>DeployModal: Click "Deploy"
    DeployModal->>DeployCtx: createVault(asset)
    activate DeployCtx
    DeployCtx->>DeployCtx: set phase='deploying'
    DeployCtx->>RPC: send transaction
    RPC-->>DeployCtx: tx receipt (CreateVaultV2 event)
    DeployCtx->>DeployCtx: decode event → vaultAddress
    DeployCtx->>Storage: addDeployedVault(vaultAddress, chainId, owner?)
    DeployCtx->>DeployCtx: set deployedVaultAddress, set phase='success'
    deactivate DeployCtx
    DeployModal->>User: show success modal
    User->>DeployModal: Click "Start Setup"
    DeployModal->>DeployCtx: navigateToVault()
    DeployCtx->>Router: route to /vault/{vaultAddress}
Loading
sequenceDiagram
    actor User
    participant InitModal as Vault Initialization Modal
    participant IndexStore as vault-indexing.ts (localStorage)
    participant Poller as useVaultIndexing hook
    participant Subgraph as Subgraph/API
    participant Toast as Toasts

    User->>InitModal: Complete deploy step
    InitModal->>IndexStore: startVaultIndexing(address, chainId)
    InitModal->>Poller: start polling
    loop every 5s
        Poller->>Subgraph: refetch adapter/market data
        Subgraph-->>Poller: not indexed yet
        Poller->>Toast: ensure "Indexing..." toast shown
    end
    Subgraph-->>Poller: adapter detected/indexed
    Poller->>Toast: clear indexing toast, show success
    Poller->>InitModal: auto-advance to next step (metadata)
Loading
sequenceDiagram
    participant API as Transactions API
    participant Grouper as transactionGrouping.ts
    participant History as HistoryTable
    participant User

    API->>Grouper: fetch user transactions
    Grouper->>Grouper: group by tx.hash
    Grouper->>Grouper: classify group (rebalance/deposits/withdrawals/unknown)
    Grouper-->>History: groupedTransactions[]
    History->>User: render grouped rows (expandable rebalance details)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • refactor: remove heroui #245: Overlapping UI refactor across many autovault/detail components (shared files and primitives changes).
  • feat: vault v2 agent wip 1 #159: Related changes to autovault deployment flow and Navbar adjustments (deployment/context/modal interactions).
  • feat: vault apy #166: Related modifications to vault data fetching and UI surface (useVaultPage, allocations, total supply changes).

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'feat: soft launch' is vague and doesn't clearly describe the main changes in the changeset, which include major API restructuring, UI modifications, and feature removals. Use a more specific title that highlights key changes, such as 'feat: vault initialization flow and deployment enhancements' or break into multiple PRs with clearer intent.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/autovault

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai bot added feature request Specific feature ready to be implemented ui User interface labels Dec 23, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/features/autovault/components/vault-detail/settings/EditCaps.tsx (1)

183-222: Missing adapter cap change detection.

The hasChanges check doesn't account for adapter cap updates. If the adapter is not authorized (or partially authorized) and the user hasn't modified any market or collateral caps, the Save button stays disabled even though handleSave would update the adapter cap. This prevents users from fixing the adapter authorization without making unrelated changes.

🔎 Proposed fix
 const hasChanges = useMemo(() => {
+  // Check for adapter cap changes
+  if (adapterAddress && existingCaps) {
+    const targetRelativeCap = parseUnits('100', 16);
+    const targetAbsoluteCap = maxUint128;
+    const currentRelativeCap = existingCaps.adapterCap ? BigInt(existingCaps.adapterCap.relativeCap) : 0n;
+    const currentAbsoluteCap = existingCaps.adapterCap ? BigInt(existingCaps.adapterCap.absoluteCap) : 0n;
+    
+    if (currentRelativeCap !== targetRelativeCap || currentAbsoluteCap !== targetAbsoluteCap) {
+      return true;
+    }
+  }
+
   // Check for new caps
   const hasNewMarkets = Array.from(marketCaps.values()).some((m) => !m.existingCapId);
   const hasNewCollaterals = Array.from(collateralCaps.values()).some((c) => !c.existingCapId);
   
   // ... rest of the checks
🧹 Nitpick comments (10)
src/components/layout/header/Navbar.tsx (1)

96-101: Autovault link correctly hidden for soft launch.

The change aligns with the PR objective. If the Autovault feature won't be re-enabled soon, consider removing the commented code instead of leaving it in place—version control preserves the history.

src/features/markets/components/markets-table-same-loan.tsx (2)

894-896: Remove unused variable.

The _selectedMarkets variable is computed but never referenced. This appears to be a leftover from the cart removal.

🔎 Proposed fix
-  const _selectedMarkets = useMemo(() => {
-    return markets.filter((m) => m.isSelected);
-  }, [markets]);
-

57-57: Remove unused prop.

The renderCartItemExtra prop is defined but never used in the component. Clean this up as part of the cart removal.

🔎 Proposed fix
   disabled?: boolean;
-  // Optional: Render additional content for selected markets in the cart
-  renderCartItemExtra?: (market: Market) => React.ReactNode;
   // Optional: Pass unique tokens for better filter performance

And remove from the function signature:

 export function MarketsTableWithSameLoanAsset({
   markets,
   onToggleMarket,
   disabled = false,
-  renderCartItemExtra,
   uniqueCollateralTokens,
src/features/autovault/components/vault-detail/settings/EditCaps.tsx (1)

237-257: Redundant condition check.

Line 238 checks if (adapterAddress) but lines 230-233 already verify adapterAddress exists and return early if not. This condition will always be true at this point.

🔎 Simplification
   const capsToUpdate: VaultV2Cap[] = [];

   // Add or fix adapter cap to ensure it's always 100% relative + maxUint128 absolute
-  if (adapterAddress) {
-    const targetRelativeCap = parseUnits('100', 16);
-    const targetAbsoluteCap = maxUint128;
+  const targetRelativeCap = parseUnits('100', 16);
+  const targetAbsoluteCap = maxUint128;

-    const currentRelativeCap = existingCaps?.adapterCap ? BigInt(existingCaps.adapterCap.relativeCap) : 0n;
-    const currentAbsoluteCap = existingCaps?.adapterCap ? BigInt(existingCaps.adapterCap.absoluteCap) : 0n;
+  const currentRelativeCap = existingCaps?.adapterCap ? BigInt(existingCaps.adapterCap.relativeCap) : 0n;
+  const currentAbsoluteCap = existingCaps?.adapterCap ? BigInt(existingCaps.adapterCap.absoluteCap) : 0n;

-    // Only update if not already at target values
-    if (currentRelativeCap !== targetRelativeCap || currentAbsoluteCap !== targetAbsoluteCap) {
-      const { params, id } = getAdapterCapId(adapterAddress);
-      capsToUpdate.push({
-        capId: id,
-        idParams: params,
-        relativeCap: targetRelativeCap.toString(),
-        absoluteCap: targetAbsoluteCap.toString(),
-        oldRelativeCap: currentRelativeCap.toString(),
-        oldAbsoluteCap: currentAbsoluteCap.toString(),
-      });
-    }
+  // Only update if not already at target values
+  if (currentRelativeCap !== targetRelativeCap || currentAbsoluteCap !== targetAbsoluteCap) {
+    const { params, id } = getAdapterCapId(adapterAddress);
+    capsToUpdate.push({
+      capId: id,
+      idParams: params,
+      relativeCap: targetRelativeCap.toString(),
+      absoluteCap: targetAbsoluteCap.toString(),
+      oldRelativeCap: currentRelativeCap.toString(),
+      oldAbsoluteCap: currentAbsoluteCap.toString(),
+    });
   }
src/features/home/home-view.tsx (1)

314-377: Remove commented-out code.

Section 4 is entirely commented out. Since version control preserves this code in history, remove it to keep the file clean and maintainable.

🔎 Proposed fix
-        {/* Section 4: Auto Vaults - Full Screen, Center Layout, No Image */}
-        {/* <section className="flex min-h-screen w-full items-center bg-main py-16 md:py-24">
-          <div className="container mx-auto px-6">
-            <div className="mx-auto max-w-3xl text-center">
-              <div className="mb-6 flex items-center justify-center gap-3">
-                <h2 className="font-zen text-4xl text-primary">
-                  Auto Vaults
-                </h2>
-                <Badge variant="success" size="lg">
-                  New
-                </Badge>
-              </div>
-              <p className="mb-8 text-2xl text-secondary">
-                Be Your Own Risk Curator
-              </p>
-
-              <div className="space-y-8">
-                <p className="text-xl leading-relaxed text-secondary">
-                  Deploy your own vault. Define your risk parameters. Keep full control.
-                </p>
-
-                <div className="space-y-6 text-left">
-                  <div className="flex items-start gap-4">
-                    <span className="font-zen text-3xl text-monarch-orange">1</span>
-                    <div>
-                      <h4 className="mb-2 font-zen text-xl text-primary">Deploy Your Vault</h4>
-                      <p className="text-lg text-secondary">
-                        Launch your own vault contract with just a few clicks. No technical expertise required.
-                      </p>
-                    </div>
-                  </div>
-
-                  <div className="flex items-start gap-4">
-                    <span className="font-zen text-3xl text-monarch-orange">2</span>
-                    <div>
-                      <h4 className="mb-2 font-zen text-xl text-primary">Full Control</h4>
-                      <p className="text-lg text-secondary">
-                        Set your own risk parameters, choose markets, define caps. You're the curator. No performance fees, no middlemen.
-                      </p>
-                    </div>
-                  </div>
-
-                  <div className="flex items-start gap-4">
-                    <span className="font-zen text-3xl text-monarch-orange">3</span>
-                    <div>
-                      <h4 className="mb-2 font-zen text-xl text-primary">Automated Optimization</h4>
-                      <p className="text-lg text-secondary">
-                        Choose automation agents that work within your rules to optimize yields automatically.
-                      </p>
-                    </div>
-                  </div>
-                </div>
-              </div>
-
-              <div className="mt-12">
-                <Link href="/autovault">
-                  <Button variant="primary" size="lg" className="px-12 py-4 font-zen">
-                    Create Auto Vault
-                  </Button>
-                </Link>
-              </div>
-            </div>
-          </div>
-        </section> */}
-
src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx (1)

265-276: Polling continues after modal closes.

This is intentional per the comment at line 307, but the polling runs for 30 seconds after init. The unmount cleanup at lines 312-319 handles this, which is good.

One issue: if the component unmounts before postInitPollingRef.current is assigned (rare race), the interval won't be cleared. Consider assigning to a local variable first.

Safer interval assignment
       // Poll every 3 seconds for up to 30 seconds (10 attempts)
       let attempts = 0;
       const maxAttempts = 10;
-      postInitPollingRef.current = setInterval(() => {
+      const intervalId = setInterval(() => {
         attempts++;
         void onAdapterConfigured();

-        if (attempts >= maxAttempts && postInitPollingRef.current) {
-          clearInterval(postInitPollingRef.current);
+        if (attempts >= maxAttempts) {
+          clearInterval(intervalId);
           postInitPollingRef.current = null;
         }
       }, 3000);
+      postInitPollingRef.current = intervalId;
src/features/autovault/vault-list-view.tsx (2)

95-100: Use Next.js router for navigation.

Direct window.location.href causes a full page reload. Use useRouter from next/navigation for client-side navigation.

Use Next.js router
+'use client';
+
+import { useRouter } from 'next/navigation';
 // ... other imports

 export default function AutovaultListContent() {
+  const router = useRouter();
   // ... other code

   const handleManageVault = () => {
     if (vaultAddresses.length > 0) {
       const firstVault = vaultAddresses[0];
-      window.location.href = `/autovault/${firstVault.networkId}/${firstVault.address}`;
+      router.push(`/autovault/${firstVault.networkId}/${firstVault.address}`);
     }
   };

71-81: Silent error handling.

Errors are logged but users get no feedback. Consider showing a toast or error state.

src/data-sources/morpho-api/v2-vaults.ts (1)

122-146: Per-address fetching can be noisy and hit rate limits.

Parallel Promise.all with many addresses may trigger API rate limiting. The console.log at line 138 will spam logs for every missing vault.

Consider:

  1. Adding request batching/throttling for large address lists
  2. Downgrading the log to console.debug or removing it
Quieter logging
       const vault = response.data?.vaultV2ByAddress;
       if (!vault) {
-        console.log(`No V2 vault found for address ${address} on network ${network}`);
+        // Vault not indexed yet or doesn't exist - this is expected for new vaults
         return null;
       }
src/features/autovault/components/deployment/deployment-context.tsx (1)

146-150: Using window.location.href causes full page reload.

Next.js apps typically use useRouter().push() for client-side navigation. Full reload loses app state and is slower.

Use Next.js router
+import { useRouter } from 'next/navigation';
 
 export function DeploymentProvider({ children }: { children: React.ReactNode }) {
+  const router = useRouter();
   // ...
 
   const navigateToVault = useCallback(() => {
     if (deployedVaultAddress && selectedTokenAndNetwork) {
-      window.location.href = `/autovault/${selectedTokenAndNetwork.networkId}/${deployedVaultAddress}`;
+      router.push(`/autovault/${selectedTokenAndNetwork.networkId}/${deployedVaultAddress}`);
     }
-  }, [deployedVaultAddress, selectedTokenAndNetwork]);
+  }, [deployedVaultAddress, selectedTokenAndNetwork, router]);
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8987c74 and b2dc09d.

📒 Files selected for processing (21)
  • src/components/layout/header/Navbar.tsx
  • src/components/layout/header/NavbarMobile.tsx
  • src/data-sources/morpho-api/v2-vaults.ts
  • src/features/autovault/components/deployment/deployment-context.tsx
  • src/features/autovault/components/deployment/deployment-modal.tsx
  • src/features/autovault/components/deployment/token-selection.tsx
  • src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx
  • src/features/autovault/components/vault-detail/settings/EditCaps.tsx
  • src/features/autovault/components/vault-detail/vault-allocator-card.tsx
  • src/features/autovault/components/vault-detail/vault-collaterals-card.tsx
  • src/features/autovault/components/vault-detail/vault-market-allocations.tsx
  • src/features/autovault/vault-list-view.tsx
  • src/features/autovault/vault-view.tsx
  • src/features/home/home-view.tsx
  • src/features/markets/components/markets-table-same-loan.tsx
  • src/features/positions/components/onboarding/market-selection-onboarding.tsx
  • src/graphql/morpho-api-queries.ts
  • src/hooks/useVaultPage.ts
  • src/hooks/useVaultV2.ts
  • src/hooks/useVaultV2Data.ts
  • src/utils/monarch-agent.ts
💤 Files with no reviewable changes (2)
  • src/hooks/useVaultV2Data.ts
  • src/features/positions/components/onboarding/market-selection-onboarding.tsx
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2024-11-25T09:39:42.148Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 87
File: app/home/HomePage.tsx:17-39
Timestamp: 2024-11-25T09:39:42.148Z
Learning: In `app/home/HomePage.tsx`, the `useEffect` hook depends on `[showCustomized]` because changing `showCustomized` triggers updates to the yield and risk terms.

Applied to files:

  • src/features/autovault/vault-list-view.tsx
  • src/features/autovault/components/deployment/deployment-modal.tsx
  • src/features/autovault/vault-view.tsx
📚 Learning: 2024-12-17T12:39:21.949Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 99
File: app/positions/components/onboarding/SuccessPage.tsx:17-17
Timestamp: 2024-12-17T12:39:21.949Z
Learning: Prefer using explicit network checks like `selectedToken?.network === SupportedNetworks.Base` over using array indexing like `config.agentSupportedNetworks[0]` for better maintainability.

Applied to files:

  • src/features/autovault/components/deployment/token-selection.tsx
📚 Learning: 2024-10-12T09:23:16.495Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 63
File: app/markets/components/MarketRowDetail.tsx:49-52
Timestamp: 2024-10-12T09:23:16.495Z
Learning: When rendering oracle feeds in `ExpandedMarketDetail` (`app/markets/components/MarketRowDetail.tsx`), prefer explicit rendering over iterating keys when dealing with a small number of feeds.

Applied to files:

  • src/features/markets/components/markets-table-same-loan.tsx
📚 Learning: 2024-12-16T02:01:51.219Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 97
File: app/positions/components/onboarding/OnboardingContext.tsx:36-43
Timestamp: 2024-12-16T02:01:51.219Z
Learning: In `app/positions/components/onboarding/OnboardingContext.tsx`, the `defaultStep` variable is no longer needed and can be removed.

Applied to files:

  • src/features/markets/components/markets-table-same-loan.tsx
  • src/components/layout/header/NavbarMobile.tsx
📚 Learning: 2025-12-09T10:06:43.810Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 231
File: src/hooks/useDeployMorphoMarketV1Adapter.ts:3-3
Timestamp: 2025-12-09T10:06:43.810Z
Learning: In Wagmi v3, useConnection is the correct hook to obtain the connected wallet address, chainId, and connection status (isConnected). This replaces the useAccount hook from Wagmi v2. Usage: const { address, chainId, isConnected } = useConnection() from 'wagmi'.

Applied to files:

  • src/features/autovault/components/deployment/deployment-context.tsx
📚 Learning: 2024-12-17T10:51:07.277Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 99
File: src/components/AgentSetupProcessModal.tsx:38-51
Timestamp: 2024-12-17T10:51:07.277Z
Learning: In `src/components/AgentSetupProcessModal.tsx`, the modal is intentionally designed without a close button.

Applied to files:

  • src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx
📚 Learning: 2025-12-09T10:06:39.848Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 231
File: src/hooks/useDeployMorphoMarketV1Adapter.ts:3-3
Timestamp: 2025-12-09T10:06:39.848Z
Learning: In Wagmi v3, useConnection is the correct hook to obtain the connected wallet address, chainId, and connection status (isConnected). This replaces the useAccount hook from Wagmi v2. In your code under src/hooks, use: const { address, chainId, isConnected } = useConnection() from 'wagmi' to access the connected wallet information.

Applied to files:

  • src/hooks/useVaultPage.ts
  • src/hooks/useVaultV2.ts
🧬 Code graph analysis (8)
src/features/autovault/vault-list-view.tsx (2)
src/data-sources/subgraph/v2-vaults.ts (1)
  • fetchUserVaultV2AddressesAllNetworks (83-92)
src/components/ui/button.tsx (1)
  • Button (107-107)
src/features/autovault/components/vault-detail/settings/EditCaps.tsx (1)
src/utils/morpho.ts (1)
  • getAdapterCapId (112-121)
src/features/autovault/components/deployment/deployment-modal.tsx (2)
src/utils/networks.ts (2)
  • ALL_SUPPORTED_NETWORKS (38-46)
  • isAgentAvailable (203-208)
src/features/autovault/components/deployment/deployment-context.tsx (1)
  • useDeployment (199-205)
src/features/autovault/components/deployment/deployment-context.tsx (1)
src/data-sources/subgraph/v2-vaults.ts (1)
  • fetchUserVaultV2Addresses (38-78)
src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx (2)
src/components/ui/spinner.tsx (1)
  • Spinner (22-58)
src/hooks/useStyledToast.tsx (1)
  • useStyledToast (6-38)
src/features/autovault/vault-view.tsx (2)
src/components/shared/tooltip-content.tsx (1)
  • TooltipContent (16-71)
src/features/autovault/components/vault-detail/vault-collaterals-card.tsx (1)
  • VaultCollateralsCard (19-84)
src/data-sources/morpho-api/v2-vaults.ts (2)
src/data-sources/morpho-api/fetchers.ts (1)
  • morphoGraphqlFetcher (4-28)
src/graphql/morpho-api-queries.ts (1)
  • vaultV2Query (538-574)
src/features/home/home-view.tsx (1)
src/components/ui/button.tsx (1)
  • Button (107-107)
🔇 Additional comments (29)
src/components/layout/header/NavbarMobile.tsx (1)

106-112: Mobile navigation updated consistently.

The Autovault item is hidden in the mobile dropdown, matching the desktop navbar change.

src/utils/monarch-agent.ts (1)

28-28: LGTM!

Description update reflecting the new 4-hour rebalance cadence.

src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx (3)

79-124: LGTM!

MetadataStep is clean. Good use of maxLength={16} on symbol to prevent overly long symbols.


321-341: Polling effect looks correct.

Cleanup properly clears the interval when dependencies change or on unmount. The 5-second interval is reasonable for adapter detection.


390-403: Validation is minimal.

Only checks non-empty after trim. Consider whether you need additional validation (e.g., no special characters, minimum length). If the contract handles this, current approach is fine.

src/features/autovault/components/vault-detail/vault-collaterals-card.tsx (1)

42-58: LGTM!

Consistent handling of needsSetup state across vault cards. Gear icon hidden during setup, orange indicator shown.

src/features/autovault/components/vault-detail/vault-allocator-card.tsx (1)

34-50: LGTM!

Same pattern as vault-collaterals-card. Consistent UI for setup-required state.

src/hooks/useVaultPage.ts (3)

69-89: LGTM!

Well-structured initialization checks with clear comments explaining each state. The check at line 88 correctly identifies complete initialization by verifying adapter cap presence.


142-146: Ownership now derived from contract.

Good change. Using contract owner instead of API data handles uninitialized vaults correctly since the API returns null for those.


45-45: owner is properly exported from useVaultV2.

The hook exports owner: vaultOwner (line 577), which derives from the smart contract's owner function. The destructuring in useVaultPage.ts is correct.

src/features/autovault/components/vault-detail/vault-market-allocations.tsx (1)

67-77: LGTM!

Clear conditional messaging for empty state. Helps users understand next steps based on vault initialization status.

src/features/autovault/vault-list-view.tsx (1)

14-50: LGTM!

Clean skeleton and benefit card components. Good loading UX.

src/graphql/morpho-api-queries.ts (1)

538-574: Query signature updated correctly - consumer already aligned.

The only consumer in src/data-sources/morpho-api/v2-vaults.ts correctly passes both address and chainId variables matching the new query signature.

src/data-sources/morpho-api/v2-vaults.ts (1)

107-119: LGTM - clean early exit and clear documentation.

Good guard clause and updated JSDoc explaining the per-address limitation.

src/hooks/useVaultV2.ts (4)

22-31: LGTM - owner read added correctly.

Properly guarded with enabled: Boolean(vaultAddress).


136-160: Metadata setting before timelock operations looks correct.

Setting name/symbol before the timelocked operations is intentional - these are non-timelocked calls.


565-577: LGTM - vaultOwner derivation is clean.

Fallback to zeroAddress is reasonable for uninitialized state.


526-533: ERC4626 withdraw parameter mapping is correct.

The third parameter _account correctly maps to the share owner per ERC4626 standard, even though vaultv2 names it onBehalf. The parameter order and semantics are correct.

src/features/autovault/components/deployment/deployment-modal.tsx (3)

41-71: LGTM - clean waiting state UI.

Good feedback during indexing wait period.


73-124: LGTM - success phase handles both outcomes.

Correctly differentiates between having a vault address (navigate) vs not (close).


163-167: Default chain fallback to Base is reasonable.

When no token is selected, defaulting to Base is fine since the button is disabled anyway.

src/features/autovault/vault-view.tsx (4)

26-69: LGTM - skeleton matches layout structure.

Grid layout mirrors VaultSummaryMetrics 4-column layout.


165-175: Early loading return is cleaner than conditional rendering.

Using vault.isLoading to show skeleton provides better UX than partial renders.


211-230: Tooltip wrapping the Button requires <span> workaround.

This is a known pattern for Radix tooltips on disabled buttons. Looks correct.


256-274: LGTM - condition updated to needsInitialization.

Banner text and logic aligned with new flow.

src/features/autovault/components/deployment/token-selection.tsx (2)

13-22: LGTM - simplified type after removing vault tracking.


44-94: LGTM - clean token aggregation logic.

Dependencies list is correct after removing existingVaults.

src/features/autovault/components/deployment/deployment-context.tsx (2)

125-144: LGTM - deployment flow with pre-count tracking.

Counting vaults before deployment to detect the new one is a solid approach.


152-167: LGTM - cleanup on reset.

Properly clears polling timers and all state.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b2dc09d and f16c355.

📒 Files selected for processing (1)
  • src/features/home/home-view.tsx

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/features/history/components/history-table.tsx (1)

229-248: Missing pageSize in useEffect dependency array.

pageSize is used in the effect but not in deps. Changing page size won't trigger a refetch.

    void loadTransactions();
- }, [account, currentPage, fetchTransactions, marketIdFilter]);
+ }, [account, currentPage, pageSize, fetchTransactions, marketIdFilter]);
🧹 Nitpick comments (6)
src/features/autovault/components/vault-detail/total-supply-card.tsx (1)

95-116: Loading state works but consider layout stability and accessibility.

The skeleton loading pattern is clean, but the fixed width (w-32) may not match the actual content width, potentially causing layout shift when data loads. Consider using a more flexible width or multiple skeleton elements to better approximate the final layout.

Additionally, the loading state has no screen reader announcement. Adding aria-live="polite" or a visually-hidden "Loading..." text would improve accessibility.

Optional improvements for layout and a11y
-            <div className="bg-hovered h-6 w-32 rounded animate-pulse" />
+            <div className="bg-hovered h-6 w-48 rounded animate-pulse" aria-label="Loading assets" />

Or for better layout approximation:

-            <div className="bg-hovered h-6 w-32 rounded animate-pulse" />
+            <div className="flex items-center gap-2">
+              <div className="bg-hovered h-6 w-24 rounded animate-pulse" />
+              <div className="bg-hovered h-5 w-5 rounded-full animate-pulse" />
+              <span className="sr-only">Loading assets</span>
+            </div>
src/features/autovault/components/vault-detail/vault-collaterals-card.tsx (1)

80-116: Tooltip for remaining collaterals shows only icons.

The remaining tokens tooltip only renders TokenIcon without the symbol text. Unlike the allocator card that shows agent.name, this only shows icons. Consider adding token symbols for better UX.

Proposed fix
                         <div
                           key={tokenAddress}
                           className="flex items-center gap-2"
                         >
                           <TokenIcon
                             address={tokenAddress}
                             chainId={chainId}
                             width={16}
                             height={16}
+                            disableTooltip={true}
                           />
+                          {/* Consider adding token symbol here if available */}
                         </div>
src/features/history/components/transaction-history-preview.tsx (1)

23-44: Duplicate formatTimeAgo function.

This exact function exists in history-table.tsx (lines 52-73). Extract to a shared utility.

Suggested location
// src/utils/time.ts
export const formatTimeAgo = (timestamp: number): string => {
  // ... implementation
};
src/features/autovault/vault-view.tsx (1)

169-190: Settings button missing <span> wrapper.

The Settings tooltip button isn't wrapped in a span like the Refresh button. If the button ever becomes disabled, the tooltip won't work.

                <Tooltip
                  content={
                    <TooltipContent
                      title="Settings"
                      detail="Configure vault settings"
                    />
                  }
                >
+                 <span>
                    <Button
                      variant="ghost"
                      size="sm"
                      className="text-secondary min-w-0 px-2"
                      onClick={() => {
                        setSettingsTab('general');
                        setShowSettings(true);
                      }}
                    >
                      <GearIcon className="h-3 w-3" />
                    </Button>
+                 </span>
                </Tooltip>
src/features/history/components/history-table.tsx (2)

52-73: Duplicate formatTimeAgo - same as transaction-history-preview.tsx.

Extract to shared utility.


808-882: Significant code duplication between deposits and withdrawals rendering.

These two blocks are nearly identical except for badge color and sign. Consider extracting a shared renderer.

Example extraction
const renderGroupedDepositWithdrawal = (
  group: GroupedTransaction,
  type: 'deposits' | 'withdrawals'
) => {
  const isDeposit = type === 'deposits';
  const badgeColor = isDeposit ? 'text-green-500' : 'text-red-500';
  const sign = isDeposit ? '+' : '-';
  const label = isDeposit ? 'Deposits' : 'Withdrawals';
  // ... shared rendering logic
};

Also applies to: 884-958

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f16c355 and d070e3f.

📒 Files selected for processing (15)
  • src/components/common/table-container-with-header.tsx
  • src/features/autovault/components/vault-detail/allocations/allocations/collateral-view.tsx
  • src/features/autovault/components/vault-detail/allocations/allocations/market-view.tsx
  • src/features/autovault/components/vault-detail/total-supply-card.tsx
  • src/features/autovault/components/vault-detail/vault-allocator-card.tsx
  • src/features/autovault/components/vault-detail/vault-collaterals-card.tsx
  • src/features/autovault/components/vault-detail/vault-market-allocations.tsx
  • src/features/autovault/vault-view.tsx
  • src/features/history/components/history-table.tsx
  • src/features/history/components/rebalance-detail.tsx
  • src/features/history/components/transaction-history-preview.tsx
  • src/features/history/history-view.tsx
  • src/features/home/home-view.tsx
  • src/utils/storageKeys.ts
  • src/utils/transactionGrouping.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/features/home/home-view.tsx
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2024-10-12T09:23:16.495Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 63
File: app/markets/components/MarketRowDetail.tsx:49-52
Timestamp: 2024-10-12T09:23:16.495Z
Learning: When rendering oracle feeds in `ExpandedMarketDetail` (`app/markets/components/MarketRowDetail.tsx`), prefer explicit rendering over iterating keys when dealing with a small number of feeds.

Applied to files:

  • src/features/history/components/rebalance-detail.tsx
  • src/features/autovault/components/vault-detail/allocations/allocations/market-view.tsx
  • src/features/autovault/components/vault-detail/vault-market-allocations.tsx
📚 Learning: 2024-10-23T16:17:02.841Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 77
File: src/graphql/queries.ts:168-193
Timestamp: 2024-10-23T16:17:02.841Z
Learning: In `src/graphql/queries.ts`, handling only `MarketTransferTransactionData` is intentional at this time.

Applied to files:

  • src/utils/transactionGrouping.ts
📚 Learning: 2024-11-25T09:39:42.148Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 87
File: app/home/HomePage.tsx:17-39
Timestamp: 2024-11-25T09:39:42.148Z
Learning: In `app/home/HomePage.tsx`, the `useEffect` hook depends on `[showCustomized]` because changing `showCustomized` triggers updates to the yield and risk terms.

Applied to files:

  • src/features/autovault/vault-view.tsx
  • src/features/history/components/history-table.tsx
🧬 Code graph analysis (8)
src/features/history/components/rebalance-detail.tsx (5)
src/utils/transactionGrouping.ts (3)
  • GroupedTransaction (3-10)
  • getWithdrawals (15-17)
  • getSupplies (22-24)
src/utils/types.ts (1)
  • Market (293-345)
src/features/markets/components/market-identity.tsx (1)
  • MarketIdentity (32-336)
src/utils/balance.ts (1)
  • formatReadable (25-49)
src/utils/oracle.ts (1)
  • getTruncatedAssetName (478-480)
src/features/autovault/components/vault-detail/allocations/allocations/market-view.tsx (4)
src/utils/vaultAllocation.ts (1)
  • calculateAllocationPercent (61-65)
src/utils/rateMath.ts (1)
  • convertApyToApr (15-29)
src/utils/balance.ts (2)
  • formatReadable (25-49)
  • formatBalance (21-23)
src/features/positions/components/allocation-cell.tsx (1)
  • AllocationCell (16-76)
src/features/autovault/components/vault-detail/total-supply-card.tsx (3)
src/components/ui/card.tsx (2)
  • CardHeader (58-58)
  • CardBody (58-58)
src/components/shared/token-icon.tsx (1)
  • TokenIcon (23-95)
src/components/ui/tooltip.tsx (1)
  • Tooltip (52-52)
src/features/autovault/components/vault-detail/allocations/allocations/collateral-view.tsx (3)
src/utils/vaultAllocation.ts (1)
  • calculateAllocationPercent (61-65)
src/utils/balance.ts (1)
  • formatBalance (21-23)
src/features/positions/components/allocation-cell.tsx (1)
  • AllocationCell (16-76)
src/features/autovault/components/vault-detail/vault-allocator-card.tsx (3)
src/utils/monarch-agent.ts (1)
  • findAgent (33-35)
src/components/shared/agent-icon.tsx (1)
  • AgentIcon (14-93)
src/components/shared/tooltip-content.tsx (1)
  • TooltipContent (16-71)
src/utils/transactionGrouping.ts (1)
src/utils/types.ts (1)
  • UserTransaction (37-49)
src/features/autovault/vault-view.tsx (4)
src/components/shared/tooltip-content.tsx (1)
  • TooltipContent (16-71)
src/features/autovault/components/vault-detail/vault-allocator-card.tsx (1)
  • VaultAllocatorCard (20-138)
src/features/autovault/components/vault-detail/vault-collaterals-card.tsx (1)
  • VaultCollateralsCard (20-127)
src/features/history/components/transaction-history-preview.tsx (1)
  • TransactionHistoryPreview (46-266)
src/features/autovault/components/vault-detail/vault-collaterals-card.tsx (4)
src/components/ui/card.tsx (2)
  • Card (58-58)
  • CardHeader (58-58)
src/components/shared/token-icon.tsx (1)
  • TokenIcon (23-95)
src/components/ui/tooltip.tsx (2)
  • Tooltip (52-52)
  • TooltipContent (52-52)
src/components/shared/tooltip-content.tsx (1)
  • TooltipContent (16-71)
🔇 Additional comments (28)
src/features/autovault/components/vault-detail/total-supply-card.tsx (3)

4-4: Icon import updated for UI refresh.

The switch to GoPlusCircle aligns with the broader iconography update across the PR.


20-20: Loading prop properly integrated.

The optional isLoading prop with a default value follows best practices and integrates cleanly with the component signature.

Also applies to: 33-33


87-87: Button styling updated for new icon.

The className adjustment and icon swap work together cleanly. The deposit button maintains its functionality with refreshed visuals.

Also applies to: 90-90

src/utils/transactionGrouping.ts (3)

1-10: Type and imports look good.

Clean type definition for GroupedTransaction. The optional fields for metaActionType and amount appropriately reflect that they're only set for meta-actions.


29-37: Rebalance amount logic is sound.

Using the minimum of supplies vs withdrawals correctly captures the "rebalanced" portion. The rest would be net deposits or withdrawals.


45-103: Grouping logic is correct, minor ordering note.

The grouping and classification logic is well-structured. One consideration: txs[0].timestamp at line 91 assumes transactions within a group have consistent timestamps. If they differ (e.g., different block times in edge cases), the timestamp would be arbitrary. This is likely fine since same-hash transactions should have the same block timestamp.

src/features/history/history-view.tsx (2)

3-11: Clean query param handling.

Using useSearchParams is the right approach for client-side query param access in Next.js.


20-24: Prop drilling looks fine.

The isVaultAdapter prop is passed through correctly. No issues here.

src/utils/storageKeys.ts (1)

25-27: New keys follow existing conventions.

Consistent monarch_ prefix and naming pattern.

src/features/autovault/components/vault-detail/allocations/allocations/collateral-view.tsx (2)

17-23: Sorting logic is correct.

Descending sort by allocation amount. Could use Number(b.allocation - a.allocation) for brevity, but explicit comparisons are readable.


34-61: AllocationCell integration looks correct.

Props match the component signature: amount (number from formatBalance), symbol, and percentage.

src/features/autovault/components/vault-detail/vault-collaterals-card.tsx (1)

54-63: Setup required state is clear.

Orange indicator with descriptive text. Consistent with the allocator card pattern.

src/components/common/table-container-with-header.tsx (1)

44-89: New variant follows existing patterns.

Good JSDoc documentation and consistent styling with TableContainerWithHeader. The description support is cleanly implemented.

src/features/autovault/components/vault-detail/vault-allocator-card.tsx (2)

65-117: Preview with tooltip pattern is well implemented.

Consistent with the collaterals card, and this one correctly shows agent names in the tooltip. Clean implementation.


31-42: No issue here—filtering is intentional design.

The component only displays agents found in v2AgentsBase (currently one known agent). This is by design: the system's initialization and settings modals restrict allocators to known agents anyway, since unknown agents lack required metadata (name, icon, description). The filtering aligns with the overall architecture constraint that allocators must come from the hardcoded known list.

src/features/history/components/rebalance-detail.tsx (2)

33-60: Row-level null return is fine.

Gracefully skipping rows when market data is missing prevents crashes. The key using both hash and idx handles potential duplicates.


64-93: Supplies rendering mirrors withdrawals.

Same pattern, consistent styling. The green/red color coding is clear.

src/features/history/components/transaction-history-preview.tsx (1)

89-134: LGTM - clean loading and empty states.

The skeleton rows and empty state handling are well structured.

src/features/autovault/components/vault-detail/allocations/allocations/market-view.tsx (2)

43-51: LGTM - clean allocation calculation.

The refactor consolidates allocation display into AllocationCell nicely. Data flow is clear: allocation (bigint) → allocatedAmount (number) and percentage (number) → AllocationCell.


31-92: Table structure is consistent with the design pattern.

Headers and cells align properly. The sorting by allocation amount (descending) is a good UX choice.

src/features/autovault/components/vault-detail/vault-market-allocations.tsx (3)

61-79: LGTM - improved loading skeleton.

The skeleton UI is much better than a spinner. Shows expected structure while loading.


81-91: LGTM - context-aware empty state.

The conditional message based on needsInitialization guides users appropriately.


93-108: LGTM - clean toggle implementation.

The view mode switch with icon is straightforward.

src/features/autovault/vault-view.tsx (3)

119-135: LGTM - error state handling.

Clean fallback UI when vault data fails to load. The back link provides a clear escape path.


148-168: Tooltip wrapper requires <span> for disabled button.

Good catch on wrapping the disabled button in a <span>. Tooltips don't work on disabled elements directly.


326-334: LGTM - TransactionHistoryPreview integration.

Correctly gated by vault.adapter existence. Props are properly passed.

src/features/history/components/history-table.tsx (2)

613-625: Good UX - warning about grouped view pagination.

Helpful to inform users about the limitation upfront.


980-1061: LGTM - settings modal implementation.

Clean modal with grouped view toggle and page size input. Persists to localStorage.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx (1)

131-139: Unused prop: isInitializing.

The prop is destructured but never used in the component. Remove it or use it to show a loading state.

Proposed fix
 function FinalizeSetupStep({
   adapter,
   registryAddress,
-  isInitializing,
 }: {
   adapter: Address;
   registryAddress: Address;
-  isInitializing: boolean;
 }) {

And at line 461:

         <FinalizeSetupStep
           adapter={marketAdapter}
           registryAddress={registryAddress}
-          isInitializing={isInitializing}
         />
♻️ Duplicate comments (2)
src/features/history/components/transaction-history-preview.tsx (2)

59-78: Missing error handling in async effect.

The loadTransactions call lacks try/catch. If the fetch fails, the component stays in loading state indefinitely and isInitialized never gets set.

Suggested fix
  useEffect(() => {
    const loadTransactions = async () => {
      if (!account || !fetchTransactions || allMarkets.length === 0) return;

+     try {
        const result = await fetchTransactions({
          userAddress: [account],
          first: limit,
          skip: 0,
          chainIds: chainId ? [chainId] : undefined,
        });

        if (result) {
          const grouped = groupTransactionsByHash(result.items);
          setHistory(grouped);
        }
+     } catch (error) {
+       console.error('Failed to fetch transactions:', error);
+     }
      setIsInitialized(true);
    };

    void loadTransactions();
  }, [account, chainId, limit, fetchTransactions, allMarkets.length]);

143-144: Fallback chainId of 1 may produce wrong explorer links.

If market isn't found and chainId prop is undefined, defaulting to mainnet will generate incorrect block explorer URLs.

🧹 Nitpick comments (8)
src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx (1)

189-191: Move constants before their usage.

MAX_NAME_LENGTH and MAX_SYMBOL_LENGTH are used in MetadataStep (lines 105, 119) but defined here. Moving them near line 26 improves readability.

src/data-sources/morpho-api/v2-vaults.ts (2)

122-146: N+1 query pattern may hit rate limits with many vaults.

Each vault triggers a separate API call. For users with many vaults, this could be slow or hit rate limits.

If the API supports batching, consider adding it. Otherwise, this is fine for now but worth monitoring.


131-134: Double error logging.

morphoGraphqlFetcher already logs and throws on GraphQL errors. This check logs again but doesn't throw - the error is silently swallowed. Consider removing the redundant check or unifying error handling.

Suggested fix
      const response = await morphoGraphqlFetcher<VaultV2ApiResponse>(vaultV2Query, variables);

-     if (response.errors && response.errors.length > 0) {
-       console.error('GraphQL errors:', response.errors);
-       return null;
-     }
-
      const vault = response.data?.vaultV2ByAddress;
src/utils/vault-indexing.ts (1)

48-48: Type assertion without validation.

JSON.parse(stored) as IndexingVault trusts localStorage content. If corrupted, this could cause runtime issues.

Optional: add basic shape validation.

Suggested fix
    const data = JSON.parse(stored) as IndexingVault;
+   if (typeof data.address !== 'string' || typeof data.chainId !== 'number' || typeof data.startTime !== 'number') {
+     localStorage.removeItem(key);
+     return null;
+   }
    const elapsed = Date.now() - data.startTime;
src/features/autovault/vault-list-view.tsx (2)

68-91: No cancellation on effect cleanup - possible stale state update.

If address or isConnected changes while fetchVaults is in flight, the old promise still runs and updates state. Consider using an abort flag or AbortController.

Suggested fix
   useEffect(() => {
     if (!address || !isConnected) {
       setVaultAddresses([]);
       setFetchError(null);
       return;
     }

+    let cancelled = false;
+
     const fetchVaults = async () => {
       setVaultsLoading(true);
       setFetchError(null);
       try {
         const addresses = await fetchUserVaultV2AddressesAllNetworks(address);
-        setVaultAddresses(addresses);
+        if (!cancelled) setVaultAddresses(addresses);
       } catch (_error) {
-        setFetchError('Unable to load vaults. Please try again.');
+        if (!cancelled) setFetchError('Unable to load vaults. Please try again.');
       } finally {
-        setVaultsLoading(false);
+        if (!cancelled) setVaultsLoading(false);
       }
     };

     void fetchVaults();
+
+    return () => {
+      cancelled = true;
+    };
   }, [address, isConnected]);

93-102: Duplicate fetch logic.

handleRetryFetch duplicates the fetch logic from the effect. Consider extracting to a shared function or just triggering a re-fetch via state.

src/features/autovault/components/deployment/deployment-context.tsx (2)

96-97: Unsafe type cast with as any.

The cast bypasses TypeScript's type checking. Consider typing the event args properly.

Suggested fix
-        const vaultAddress = (decoded.args as any).newVaultV2 as Address;
+        const vaultAddress = (decoded.args as { newVaultV2: Address }).newVaultV2;

Or define a proper type for the CreateVaultV2 event args based on your ABI.


109-111: Silent failure on error.

User gets no feedback when deployment fails - just returns to selection phase. Consider showing an error toast.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d070e3f and 706c564.

📒 Files selected for processing (17)
  • src/data-sources/morpho-api/fetchers.ts
  • src/data-sources/morpho-api/v2-vaults.ts
  • src/data-sources/subgraph/v2-vaults.ts
  • src/features/autovault/components/deployment/deployment-context.tsx
  • src/features/autovault/components/deployment/deployment-modal.tsx
  • src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx
  • src/features/autovault/components/vault-detail/vault-market-allocations.tsx
  • src/features/autovault/vault-list-view.tsx
  • src/features/autovault/vault-view.tsx
  • src/features/history/components/transaction-history-preview.tsx
  • src/graphql/morpho-v2-subgraph-queries.ts
  • src/hooks/useCreateVault.ts
  • src/hooks/useVaultIndexing.ts
  • src/hooks/useVaultPage.ts
  • src/hooks/useVaultV2.ts
  • src/utils/vault-indexing.ts
  • src/utils/vault-storage.ts
🧰 Additional context used
🧠 Learnings (8)
📚 Learning: 2025-12-09T10:06:39.848Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 231
File: src/hooks/useDeployMorphoMarketV1Adapter.ts:3-3
Timestamp: 2025-12-09T10:06:39.848Z
Learning: In Wagmi v3, useConnection is the correct hook to obtain the connected wallet address, chainId, and connection status (isConnected). This replaces the useAccount hook from Wagmi v2. In your code under src/hooks, use: const { address, chainId, isConnected } = useConnection() from 'wagmi' to access the connected wallet information.

Applied to files:

  • src/hooks/useVaultPage.ts
  • src/hooks/useCreateVault.ts
  • src/hooks/useVaultIndexing.ts
  • src/hooks/useVaultV2.ts
📚 Learning: 2024-10-12T09:23:16.495Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 63
File: app/markets/components/MarketRowDetail.tsx:49-52
Timestamp: 2024-10-12T09:23:16.495Z
Learning: When rendering oracle feeds in `ExpandedMarketDetail` (`app/markets/components/MarketRowDetail.tsx`), prefer explicit rendering over iterating keys when dealing with a small number of feeds.

Applied to files:

  • src/features/autovault/components/vault-detail/vault-market-allocations.tsx
📚 Learning: 2024-12-17T12:39:21.949Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 99
File: app/positions/components/onboarding/SuccessPage.tsx:17-17
Timestamp: 2024-12-17T12:39:21.949Z
Learning: Prefer using explicit network checks like `selectedToken?.network === SupportedNetworks.Base` over using array indexing like `config.agentSupportedNetworks[0]` for better maintainability.

Applied to files:

  • src/data-sources/subgraph/v2-vaults.ts
📚 Learning: 2024-11-25T09:39:42.148Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 87
File: app/home/HomePage.tsx:17-39
Timestamp: 2024-11-25T09:39:42.148Z
Learning: In `app/home/HomePage.tsx`, the `useEffect` hook depends on `[showCustomized]` because changing `showCustomized` triggers updates to the yield and risk terms.

Applied to files:

  • src/features/autovault/vault-list-view.tsx
  • src/features/autovault/components/deployment/deployment-modal.tsx
  • src/features/autovault/vault-view.tsx
📚 Learning: 2024-12-17T10:51:07.277Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 99
File: src/components/AgentSetupProcessModal.tsx:38-51
Timestamp: 2024-12-17T10:51:07.277Z
Learning: In `src/components/AgentSetupProcessModal.tsx`, the modal is intentionally designed without a close button.

Applied to files:

  • src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx
📚 Learning: 2024-10-23T16:17:02.841Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 77
File: src/graphql/queries.ts:168-193
Timestamp: 2024-10-23T16:17:02.841Z
Learning: In `src/graphql/queries.ts`, handling only `MarketTransferTransactionData` is intentional at this time.

Applied to files:

  • src/features/history/components/transaction-history-preview.tsx
📚 Learning: 2024-12-16T02:01:51.219Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 97
File: app/positions/components/onboarding/OnboardingContext.tsx:36-43
Timestamp: 2024-12-16T02:01:51.219Z
Learning: In `app/positions/components/onboarding/OnboardingContext.tsx`, the `defaultStep` variable is no longer needed and can be removed.

Applied to files:

  • src/features/autovault/components/deployment/deployment-context.tsx
📚 Learning: 2025-12-09T10:06:43.810Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 231
File: src/hooks/useDeployMorphoMarketV1Adapter.ts:3-3
Timestamp: 2025-12-09T10:06:43.810Z
Learning: In Wagmi v3, useConnection is the correct hook to obtain the connected wallet address, chainId, and connection status (isConnected). This replaces the useAccount hook from Wagmi v2. Usage: const { address, chainId, isConnected } = useConnection() from 'wagmi'.

Applied to files:

  • src/features/autovault/components/deployment/deployment-context.tsx
🧬 Code graph analysis (9)
src/features/autovault/components/vault-detail/vault-market-allocations.tsx (1)
src/components/common/table-container-with-header.tsx (1)
  • TableContainerWithDescription (70-89)
src/data-sources/morpho-api/v2-vaults.ts (2)
src/data-sources/morpho-api/fetchers.ts (1)
  • morphoGraphqlFetcher (4-29)
src/graphql/morpho-api-queries.ts (1)
  • vaultV2Query (538-574)
src/hooks/useVaultIndexing.ts (2)
src/hooks/useStyledToast.tsx (1)
  • useStyledToast (6-38)
src/utils/vault-indexing.ts (2)
  • getIndexingVault (41-63)
  • stopVaultIndexing (68-75)
src/features/autovault/vault-list-view.tsx (3)
src/data-sources/subgraph/v2-vaults.ts (1)
  • fetchUserVaultV2AddressesAllNetworks (80-89)
src/utils/vault-storage.ts (1)
  • getDeployedVaults (52-65)
src/components/ui/button.tsx (1)
  • Button (107-107)
src/features/autovault/components/deployment/deployment-modal.tsx (3)
src/utils/networks.ts (2)
  • ALL_SUPPORTED_NETWORKS (38-46)
  • isAgentAvailable (203-208)
src/features/autovault/components/deployment/deployment-context.tsx (1)
  • useDeployment (156-162)
src/components/ui/button.tsx (1)
  • Button (107-107)
src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx (2)
src/hooks/useStyledToast.tsx (1)
  • useStyledToast (6-38)
src/utils/vault-indexing.ts (1)
  • startVaultIndexing (22-34)
src/hooks/useVaultV2.ts (1)
src/abis/vaultv2.ts (1)
  • vaultv2Abi (3-3)
src/features/history/components/transaction-history-preview.tsx (6)
src/utils/transactionGrouping.ts (1)
  • groupTransactionsByHash (45-103)
src/components/common/table-container-with-header.tsx (1)
  • TableContainerWithDescription (70-89)
src/components/shared/transaction-identity.tsx (1)
  • TransactionIdentity (19-32)
src/utils/types.ts (1)
  • Market (293-345)
src/utils/balance.ts (1)
  • formatReadable (25-49)
src/utils/oracle.ts (1)
  • getTruncatedAssetName (478-480)
src/features/autovault/components/deployment/deployment-context.tsx (1)
src/utils/vault-storage.ts (1)
  • addDeployedVault (22-47)
🔇 Additional comments (39)
src/data-sources/subgraph/v2-vaults.ts (3)

42-42: LGTM - reduces runtime noise.

Replacing the log with a comment is appropriate for this non-error condition.


62-62: LGTM - consistent with line 42.

Removing the log for the no-vaults case keeps logs cleaner.


67-70: LGTM - cleaner direct return.

Removing the intermediate variable and log simplifies the code without changing behavior.

src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx (9)

28-47: LGTM!

Clean step indicator implementation.


49-81: LGTM!

Status messaging covers the relevant states well.


163-187: LGTM!

Agent selection logic is straightforward.


240-250: LGTM!

Error handling deferred to hook is fine; statusVisible state drives UI feedback.


252-290: LGTM!

Validation, initialization, and indexing flow is well-structured.


292-306: LGTM!

State and interval cleanup on close is thorough.


352-423: LGTM!

CTA logic per step is clear with proper disabled states.


425-477: LGTM!

Modal structure is clean. Step rendering and footer layout look good.


308-328: refetchMarketAdapter is already wrapped in useCallback.

The parent component passes handleRefetchAdapter (lines 104-106) which is properly memoized with useCallback, so the polling interval won't restart unnecessarily on parent re-renders.

src/graphql/morpho-v2-subgraph-queries.ts (1)

4-17: LGTM!

Query ordering by createdAtBlockNumber desc ensures newest vaults first. Added timestamp fields are useful.

src/hooks/useCreateVault.ts (1)

46-93: LGTM!

Return type change to Promise<string | undefined> allows callers to track the tx hash. Error handling with broader rejection check is good.

src/features/history/components/transaction-history-preview.tsx (1)

24-45: LGTM!

formatTimeAgo handles all time ranges well.

src/data-sources/morpho-api/fetchers.ts (1)

8-13: LGTM!

cache: 'no-store' ensures fresh data. Appropriate for vault state that changes frequently.

src/hooks/useVaultV2.ts (4)

22-31: LGTM!

Reading owner directly from contract is the right approach for uninitialized vaults where API data is unavailable.


136-160: LGTM!

Optional metadata setting during initialization improves UX by reducing transaction count. The trim() calls prevent empty string submissions.


565-568: LGTM!

vaultOwner memoization with zeroAddress fallback is clean.


526-533: No changes needed. The withdraw function signature matches the vault ABI: the third parameter (onBehalf in the ABI) correctly represents the share owner and is being passed as _account by callers. ERC4626 compliance is maintained; the parameter name differs (onBehalf vs standard owner) but the semantics and position are correct.

Likely an incorrect or invalid review comment.

src/hooks/useVaultPage.ts (3)

60-84: LGTM!

Clear state machine with good documentation. The initialization check correctly handles the loading/adapter/API data progression.


137-141: LGTM!

Using contractOwner for ownership check is correct since API returns null for uninitialized vaults.


173-174: LGTM!

Including allocationsLoading in the combined loading state prevents partial renders.

src/utils/vault-indexing.ts (1)

1-75: LGTM!

Clean localStorage utility with auto-cleanup. Error handling and address normalization are good.

src/hooks/useVaultIndexing.ts (2)

138-138: styledToast in deps may cause effect re-runs.

useStyledToast returns new callback references on each render unless it memoizes them internally. This could trigger the effect repeatedly. Based on the snippet at lines 5-37 of useStyledToast.tsx, the callbacks are memoized with useCallback, so this should be fine.


140-154: Cleanup effect looks good.

Properly clears intervals, dismisses toasts, and resets the detection flag on unmount.

src/features/autovault/vault-list-view.tsx (2)

15-52: Skeleton and BenefitCard components are clean.

Simple, well-structured presentational components.


112-134: Merge logic is correct.

Properly combines API results with local storage, avoiding duplicates via Set lookup.

src/features/autovault/components/vault-detail/vault-market-allocations.tsx (2)

61-79: Loading state handles both data sources.

Good that it waits for both isLoading and marketsLoading before showing content.


100-131: Clean conditional rendering.

Empty state messages are clear and context-aware. The TableContainerWithDescription wrapper is well integrated.

src/utils/vault-storage.ts (1)

22-47: Storage logic is solid.

Proper duplicate checking with case-insensitive address comparison. Silent failure with console warning is appropriate for localStorage operations.

src/features/autovault/components/deployment/deployment-modal.tsx (2)

42-92: Success modal flow is clean.

Good separation between "has vault address" (show Start Setup) and fallback (show Close). The conditional messaging at lines 65-68 is clear.


130-140: Button state logic simplified.

Disabled condition is straightforward. The default to SupportedNetworks.Base is fine as a fallback since the button is disabled without selection anyway.

src/features/autovault/vault-view.tsx (4)

81-92: Indexing integration looks correct.

isDataLoaded computation properly checks loading, error, and data presence. Hook receives necessary params for polling and refetch.


134-166: Loading skeleton during indexing.

Good UX - prevents jarring content shifts while waiting for indexing to complete.


376-384: TransactionHistoryPreview gating.

Only shown when vault has adapter, is initialized, and caps are configured. The emptyMessage is helpful for new vaults.


206-216: Tooltip requires span wrapper around disabled button.

Wrapping the Button in a <span> is a common pattern to allow tooltips on disabled elements. Works correctly.

src/features/autovault/components/deployment/deployment-context.tsx (2)

58-112: Deployment flow extracts address from receipt.

This addresses the past review comment about .at(-1) ordering - now correctly parses the event from the transaction receipt rather than polling. Clean approach.


114-118: Navigation helper is straightforward.

Correct dependency array. Routes to the right path when vault address is available.

Comment on lines +230 to +235
const tx = group.transactions[0];
const market = allMarkets.find((m) => m.uniqueKey === tx.data.market.uniqueKey) as Market | undefined;
const sign = tx.type === 'MarketSupply' ? '+' : '-';
const side = tx.type === 'MarketSupply' ? 'Supply' : 'Withdraw';

if (!market) return null;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Silent null return hides rows without explanation.

When market is not found, returning null silently removes the row. Users see fewer transactions than expected with no indication why.

Consider logging or filtering these out before rendering.

🤖 Prompt for AI Agents
In src/features/history/components/transaction-history-preview.tsx around lines
230 to 235, the code currently returns null when a market lookup fails which
silently omits rows; instead, filter out transactions with missing markets
upstream (e.g., before mapping/rendering) or explicitly handle the case by
logging a warning with identifying info (transaction id/type/market key) and
return a clear placeholder UI (or skip consistently) so users/developers can see
missing data; implement one consistent approach: either pre-filter the dataset
to remove invalid transactions or replace the null return with a logged warning
and a small fallback row indicating "Market unavailable".

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (3)
src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx (3)

374-387: Consider trimming input values on change or before validation.

Validation checks .trim().length but doesn't trim the state values, so whitespace is passed to completeInitialization. While Line 254's comment indicates backend trimming occurs in useVaultV2, trimming on input would improve consistency.

🔎 Trim on change
 <Input
   size="sm"
   value={vaultName}
-  onChange={(event) => onNameChange(event.target.value)}
+  onChange={(event) => onNameChange(event.target.value.trim())}
   placeholder="e.g., Automonarch USD"

Apply similarly to vaultSymbol input.


389-401: Optional: Clarify that agent selection is required.

The button is disabled when no agent is selected, but the step description doesn't explicitly state this is required. Consider adding "(required)" to the description or step title.


188-189: Consider moving constants to the top of the file.

MAX_NAME_LENGTH and MAX_SYMBOL_LENGTH are defined mid-file. Moving them near the other constants (lines 18-24) would improve consistency.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 579242b and c459082.

📒 Files selected for processing (3)
  • src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx
  • src/hooks/useVaultIndexing.tsx
  • src/utils/vault-storage.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/utils/vault-storage.ts
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2024-12-16T02:01:51.219Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 97
File: app/positions/components/onboarding/OnboardingContext.tsx:36-43
Timestamp: 2024-12-16T02:01:51.219Z
Learning: In `app/positions/components/onboarding/OnboardingContext.tsx`, the `defaultStep` variable is no longer needed and can be removed.

Applied to files:

  • src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx
📚 Learning: 2025-12-09T10:06:43.810Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 231
File: src/hooks/useDeployMorphoMarketV1Adapter.ts:3-3
Timestamp: 2025-12-09T10:06:43.810Z
Learning: In Wagmi v3, useConnection is the correct hook to obtain the connected wallet address, chainId, and connection status (isConnected). This replaces the useAccount hook from Wagmi v2. Usage: const { address, chainId, isConnected } = useConnection() from 'wagmi'.

Applied to files:

  • src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx
📚 Learning: 2024-12-17T10:51:07.277Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 99
File: src/components/AgentSetupProcessModal.tsx:38-51
Timestamp: 2024-12-17T10:51:07.277Z
Learning: In `src/components/AgentSetupProcessModal.tsx`, the modal is intentionally designed without a close button.

Applied to files:

  • src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx
🧬 Code graph analysis (2)
src/hooks/useVaultIndexing.tsx (3)
src/hooks/useStyledToast.tsx (1)
  • useStyledToast (6-38)
src/utils/vault-indexing.ts (2)
  • getIndexingVault (41-63)
  • stopVaultIndexing (68-75)
src/components/ui/styled-toast.tsx (1)
  • StyledToast (3-10)
src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx (2)
src/components/ui/spinner.tsx (1)
  • Spinner (22-58)
src/utils/vault-indexing.ts (1)
  • startVaultIndexing (22-34)
🔇 Additional comments (6)
src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx (5)

48-80: LGTM - enhanced deployment status messaging.

The updated props and conditional messaging improve UX by clearly indicating adapter detection states.


130-160: LGTM - clean finalization step.

Simplified display using shortened addresses is appropriate for the review step.


289-303: LGTM - comprehensive cleanup on modal close.

State and interval cleanup is properly implemented, preventing memory leaks and stale state.


99-123: No action needed. The Input component properly supports the maxLength prop through standard HTML input attributes. The component accepts all React.InputHTMLAttributes (including maxLength) and passes them to the native input element, which natively enforces the constraint.

Likely an incorrect or invalid review comment.


305-325: No action needed. The refetchMarketAdapter prop (which is handleRefetchAdapter in the parent) is already memoized with useCallback, so the polling interval won't restart unnecessarily on re-renders.

src/hooks/useVaultIndexing.tsx (1)

132-143: Verify if indexing state should persist across unmounts.

The unmount cleanup doesn't call stopVaultIndexing(vaultAddress, chainId), leaving the indexing state in localStorage. If this is intentional (to resume indexing after navigation), that's fine. Otherwise, stale state will persist until the timeout (2 minutes).

Clarify the intended behavior: should indexing state survive component unmount, or should it be cleaned up immediately?

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/features/home/home-view.tsx (1)

350-350: Text change in commented code has no effect.

This line is inside a commented-out section (lines 313-376), so the text change from "No performance fees" to "No hidden fees" doesn't affect the rendered page. Consider removing the change or uncommenting if this section is planned for near-term use.

src/hooks/useVaultPage.ts (1)

85-85: Consider simplifying the null check.

The explicit vaultData !== null && vaultData !== undefined works but can be shortened to vaultData != null (loose equality null check covers both null and undefined).

🔎 Simplified check
-    return vaultData !== null && vaultData !== undefined;
+    return vaultData != null;
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c459082 and 107027c.

📒 Files selected for processing (11)
  • src/features/autovault/components/deployment/token-selection.tsx
  • src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx
  • src/features/autovault/vault-list-view.tsx
  • src/features/autovault/vault-view.tsx
  • src/features/home/home-view.tsx
  • src/graphql/morpho-v2-subgraph-queries.ts
  • src/hooks/useDeployMorphoMarketV1Adapter.ts
  • src/hooks/useVaultIndexing.tsx
  • src/hooks/useVaultPage.ts
  • src/hooks/useVaultV2.ts
  • src/utils/monarch-agent.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/graphql/morpho-v2-subgraph-queries.ts
  • src/hooks/useVaultIndexing.tsx
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2024-12-16T02:01:51.219Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 97
File: app/positions/components/onboarding/OnboardingContext.tsx:36-43
Timestamp: 2024-12-16T02:01:51.219Z
Learning: In `app/positions/components/onboarding/OnboardingContext.tsx`, the `defaultStep` variable is no longer needed and can be removed.

Applied to files:

  • src/features/home/home-view.tsx
  • src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx
📚 Learning: 2025-12-09T10:06:39.848Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 231
File: src/hooks/useDeployMorphoMarketV1Adapter.ts:3-3
Timestamp: 2025-12-09T10:06:39.848Z
Learning: In Wagmi v3, useConnection is the correct hook to obtain the connected wallet address, chainId, and connection status (isConnected). This replaces the useAccount hook from Wagmi v2. In your code under src/hooks, use: const { address, chainId, isConnected } = useConnection() from 'wagmi' to access the connected wallet information.

Applied to files:

  • src/hooks/useVaultPage.ts
  • src/hooks/useDeployMorphoMarketV1Adapter.ts
  • src/hooks/useVaultV2.ts
📚 Learning: 2024-12-17T12:39:21.949Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 99
File: app/positions/components/onboarding/SuccessPage.tsx:17-17
Timestamp: 2024-12-17T12:39:21.949Z
Learning: Prefer using explicit network checks like `selectedToken?.network === SupportedNetworks.Base` over using array indexing like `config.agentSupportedNetworks[0]` for better maintainability.

Applied to files:

  • src/utils/monarch-agent.ts
  • src/features/autovault/components/deployment/token-selection.tsx
📚 Learning: 2024-11-25T09:39:42.148Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 87
File: app/home/HomePage.tsx:17-39
Timestamp: 2024-11-25T09:39:42.148Z
Learning: In `app/home/HomePage.tsx`, the `useEffect` hook depends on `[showCustomized]` because changing `showCustomized` triggers updates to the yield and risk terms.

Applied to files:

  • src/features/autovault/vault-view.tsx
  • src/features/autovault/vault-list-view.tsx
📚 Learning: 2025-11-13T20:32:48.908Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 183
File: app/positions/components/RebalanceModal.tsx:301-308
Timestamp: 2025-11-13T20:32:48.908Z
Learning: The TokenIcon component in the codebase accepts a `symbol` prop as part of its valid interface, in addition to `address`, `chainId`, `width`, `height`, and other props.

Applied to files:

  • src/features/autovault/components/deployment/token-selection.tsx
📚 Learning: 2024-12-17T10:51:07.277Z
Learnt from: antoncoding
Repo: antoncoding/monarch PR: 99
File: src/components/AgentSetupProcessModal.tsx:38-51
Timestamp: 2024-12-17T10:51:07.277Z
Learning: In `src/components/AgentSetupProcessModal.tsx`, the modal is intentionally designed without a close button.

Applied to files:

  • src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx
🧬 Code graph analysis (4)
src/features/autovault/vault-view.tsx (3)
src/hooks/useVaultIndexing.tsx (1)
  • useVaultIndexing (20-151)
src/components/ui/tooltip.tsx (2)
  • Tooltip (52-52)
  • TooltipContent (52-52)
src/components/shared/tooltip-content.tsx (1)
  • TooltipContent (16-71)
src/features/autovault/components/deployment/token-selection.tsx (3)
src/features/autovault/components/deployment/deployment-context.tsx (1)
  • useDeployment (156-162)
src/components/providers/TokenProvider.tsx (1)
  • useTokens (131-137)
src/utils/balance.ts (1)
  • formatReadable (25-49)
src/features/autovault/vault-list-view.tsx (3)
src/data-sources/subgraph/v2-vaults.ts (1)
  • fetchUserVaultV2AddressesAllNetworks (80-89)
src/utils/vault-storage.ts (1)
  • getDeployedVaults (52-65)
src/components/ui/button.tsx (1)
  • Button (107-107)
src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx (4)
src/utils/morpho.ts (1)
  • getMorphoAddress (8-27)
src/utils/networks.ts (1)
  • getNetworkConfig (183-185)
src/abis/morpho-market-v1-adapter-factory.ts (1)
  • adapterFactoryAbi (3-3)
src/utils/vault-indexing.ts (1)
  • startVaultIndexing (22-34)
🔇 Additional comments (26)
src/features/home/home-view.tsx (1)

284-295: Auto Vault button is now functional and correctly styled.

The Link wrapper properly enables navigation to /autovault, and the button no longer has misleading disabled styling. Good fix.

src/utils/monarch-agent.ts (1)

14-14: This is a metadata-only update with no codebase inconsistencies.

The description change from "8 hours" to "4 hours" updates only user-facing text. No conflicting references to the old schedule exist in the codebase, and no hardcoded rebalance intervals are implemented in TypeScript. The actual rebalance logic resides in the on-chain smart contract (address 0x038cC0fFf3aBc20dcd644B1136F42A33df135c52), so matching the agent's behavior requires verifying the contract implementation separately.

src/hooks/useVaultPage.ts (2)

202-245: Summary claims contractOwner is exposed, but it's missing from the return object.

The AI summary states "Exposed contractOwner alias (on-chain owner)" but the return object only exposes the derived isOwner boolean (line 218), not the raw contractOwner address. If consuming components need access to the owner address, consider adding it to the return object.


62-201: Initialization flow logic is well-structured.

The new isVaultInitialized and needsInitialization computed states correctly model the vault deployment stages. The ownership derivation properly switched to on-chain data (contractOwner) to handle uninitialized vaults where the API returns null. The loading synchronization (line 176) now correctly waits for all parallel queries.

src/hooks/useDeployMorphoMarketV1Adapter.ts (1)

49-63: LGTM!

The explicit return type and transaction hash propagation improve caller observability. Early exit handling is clear.

src/hooks/useVaultV2.ts (5)

22-31: LGTM!

Owner read via useReadContract follows Wagmi v3 patterns correctly.


88-88: Dynamic toast IDs prevent collisions.

Including vaultAddress in toast IDs allows multiple vault operations to show distinct toasts simultaneously.

Also applies to: 102-102, 112-112, 123-123, 474-474, 485-485


525-531: Parameter rename aligns with ERC-4626.

The _account parameter name matches the ERC-4626 standard signature for withdraw(uint256 assets, address receiver, address owner).


563-575: LGTM!

The vaultOwner memo safely handles undefined and exposes owner in the hook's return value.


135-262: No action needed. setName and setSymbol are owner-only functions that execute instantly without timelock, so wrapping them in submit() would be incorrect. The code handles these correctly by encoding them directly.

Likely an incorrect or invalid review comment.

src/features/autovault/vault-list-view.tsx (5)

64-66: LGTM!

The mounting guard prevents hydration mismatches between server and client.

Also applies to: 150-150, 168-168


68-91: LGTM!

Fetch logic handles loading, error states, and empty results cleanly. Errors don't clear existing data, which is good UX.


136-141: LGTM!

Navigation to the first vault provides a quick entry point when multiple vaults exist.


148-262: LGTM!

UI restructure cleanly handles loading, error, connected/not-connected, and vault ownership states. The hero section and benefits grid provide a clear value proposition.


112-134: The merge logic already uses .toLowerCase() for the dedup key comparison, so it safely handles address casing inconsistencies. Both sources (subgraph and local storage) should return addresses consistently, but the code is protected regardless.

src/features/autovault/components/deployment/token-selection.tsx (3)

114-126: LGTM!

Sort logic places USDC Base first, then by balance descending, then alphabetically. This provides a predictable and user-friendly ordering.


178-233: LGTM!

The "Suggested" badge clearly indicates USDC Base with 0 balance, helping users understand the default choice.


13-15: This address is the official USDC contract on Base.

src/features/autovault/components/vault-detail/modals/vault-initialization-modal.tsx (4)

237-285: LGTM!

The deploy flow waits for the transaction receipt and decodes the CreateMorphoMarketV1Adapter event to extract the adapter address. This ensures the adapter address is captured immediately without waiting for subgraph indexing.


287-325: LGTM!

The initialization flow passes name/symbol to completeInitialization, then starts vault indexing and triggers a refetch. Error handling relies on the hook's toast, which is appropriate.


74-120: LGTM!

The MetadataStep component provides clear input fields with appropriate placeholders and length limits.


180-181: Verify that contract enforces matching length constraints on name and symbol.

The UI enforces MAX_NAME_LENGTH = 64 and MAX_SYMBOL_LENGTH = 16 via input maxLength attributes, but contract source code is not available in this repository to confirm these match any on-chain constraints. If the contract doesn't enforce the same limits, inputs could succeed on the UI and then fail during transaction execution.

src/features/autovault/vault-view.tsx (4)

84-168: LGTM!

The useVaultIndexing hook integration provides a smooth loading experience during indexing, with a skeleton UI preventing layout shifts.


194-243: LGTM!

Tooltip-wrapped Refresh and Settings buttons improve discoverability and explain their purpose clearly.


378-386: LGTM!

Transaction history is only shown when the vault is fully initialized and caps are configured, which prevents showing an empty history during setup.


429-430: LGTM!

The completeInitialization and isInitializing props are correctly passed to the initialization modal, enabling the full setup flow.

@antoncoding antoncoding merged commit 3cfba71 into master Dec 24, 2025
4 checks passed
@antoncoding antoncoding deleted the feat/autovault branch December 24, 2025 13:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature request Specific feature ready to be implemented ui User interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant