Skip to content

Conversation

@vutuanlinh2k2
Copy link
Contributor

Summary

This PR contains comprehensive QA fixes and improvements across the restaking, liquid staking, and migration claim flows:

Restaking Improvements

  • Use on-chain data as source of truth: The RestakeContext now merges GraphQL data with on-chain delegator data to ensure accurate deposit/delegation amounts, fixing issues where the indexer could have stale data
  • Rename unstake → undelegate: Consistent terminology across the codebase (folder renamed from unstake/ to undelegate/)
  • Show request count badge: The expand table button now displays a badge showing the number of pending requests (undelegate/withdraw)
  • Fix delegate navigation: Clicking delegate on the operators tab now properly navigates to the delegate flow
  • Fix chain ID resolution: GraphQL hooks now use the network store's chain ID when wallet is not connected, preventing incorrect data fetching

Liquid Staking Improvements

  • Pre-select vault from URL: Deposit and redeem forms now read ?vault=<address> from the URL to pre-select the vault
  • Improve UI consistency: Added TokenIcon components and better styling throughout vault selection
  • Optimistic redeem updates: Redeem requests now show immediately in the UI while waiting for indexer to catch up
  • Fix vault asset lookup: Address normalization to lowercase prevents mismatches between indexer and on-chain data

Migration Claim Improvements

  • Wallet mode banner: Shows a banner when the claim relayer is unavailable, informing users they can still claim directly via wallet
  • Better proof progress: Simplified proof polling progress messages
  • Full TangleMigration ABI: Added complete ABI for better type safety

Infrastructure

  • Chain-aware token metadata: Token metadata cache is now keyed by chain ID to prevent cross-chain collisions when switching networks
  • Base Sepolia support: Added Base Sepolia chain icon and updated token address mappings
  • Code cleanup: Extracted useFormSetValue hook to reduce duplication across forms

Test plan

  • Test restaking deposit flow with wallet connected and disconnected
  • Test delegate flow navigation from operators tab
  • Test undelegate flow and verify request count badge updates
  • Test withdraw flow and verify request count badge updates
  • Test liquid staking deposit with ?vault=<address> URL parameter
  • Test liquid staking redeem with optimistic updates
  • Test migration claim flow with and without relayer
  • Verify no cross-chain data issues when switching networks

🤖 Generated with Claude Code

vutuanlinh2k2 and others added 30 commits December 22, 2025 18:52
- Normalize vault asset addresses to lowercase for proper indexer matching
- Add TokenIcon to vault selection in deposit/redeem pages
- Improve vault display names (use underlying asset symbol)
- Simplify redeem page UI with cleaner shares display
- Show approximate asset value on pending redeem claims
- Fix TransactionInputCard max amount handling for small values
- Update local Anvil contract and token addresses

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…staking pages

- Use getRoundedAmountString for consistent amount formatting in tables
- Add proper icons and avatars for selected operator/asset in create vault
- Use OperatorListItem and AssetListItem components for better list rendering
- Show approximate asset value inline with shares in redeem page

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…osit/redeem forms

When clicking Deposit/Redeem buttons in Vaults/Positions tables, the vault
is now automatically pre-selected in the corresponding form based on the
?vault= query parameter. Also unified the Redeem button style to match
the Deposit button.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ain collisions

Token metadata cache and lookups were not chain-aware, causing incorrect
metadata to be returned when users switched between networks (e.g., same
address could represent different tokens on different chains).

Changes:
- Restructure KNOWN_TOKEN_ADDRESSES to be keyed by chainId
- Update metadataCache key format from "address" to "chainId:address"
- Add chainId parameter to getCachedTokenMetadata, cacheTokenMetadata,
  and resolveTokenMetadata functions
- Update all consumers to pass chainId from wagmi/viem

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ing operations

Add txName and txDetails to liquid staking hooks so transactions display
meaningful information in the TxHistoryDrawer:
- Deposit: shows token address and amount with correct symbol
- Request redeem: shows asset address and shares count
- Redeem: shows asset address and shares count

Also fix shares formatting to display without a token symbol suffix.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…earer labels

- Rename share columns for clarity: "Your Shares" vs "Total Shares"
- Add optimistic redeem request display to avoid waiting for indexer
- Refetch user position after redeem/claim for immediate UI updates
- Fix TxConfirmationModal to not append token symbol to share amounts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Apply code formatting fixes across multiple files (dependency arrays, type annotations)
- Remove approximate asset value display from liquid staking redeem page to reduce confusion
- Convert ABI files from JSON-style to JavaScript object-style formatting

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The commit 15279a9 synced ABIs from tnt-core with a new diamond pattern
contract architecture, but the dapp code still expects the old function
signatures (delegate, deposit, claimDelegatorRewards, etc.).

- Revert multiAssetDelegation.ts, tangle.ts, blueprintServiceManager.ts,
  and operatorStatusRegistry.ts to pre-sync versions
- Fix parseEventLogs type assertion in useServiceRequest.ts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Conflicts resolved:
- tokenMetadata.ts: kept chain-separated structure, merged v2 addresses
- claim-relayer: accepted deletion
- multiAssetDelegation.ts: accepted v2 ABI
- tangle.ts: accepted v2 ABI

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix NetworkType usage in processLeaderboardRecord.ts (use string literal)
- Add chainId parameter to getCachedTokenMetadata call in RestakingAssetsTable
- Import EIP1193Provider from viem in useViemWalletClient
- Update Deposit button in VaultsTable to match Redeem button style

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Critical fixes:
- Replace incorrect useRef with useMemo for static Icon objects
- Fix memory leak from uncleaned setTimeout in redeem form
- Fix optimistic requests claimable check by filtering out unindexed requests
- Sync form state with useAllBlueprints in create-vault
- Add timestamp tolerance to optimistic request cleanup to prevent race conditions

Important fixes:
- Remove fragile error string matching for ERC20 approval retry
- Fix auto-close timer to check tx hash before closing modal
- Limit dismissedHashes Set size to prevent memory growth
- Standardize isNumericString to use faster regex implementation

Suggestions:
- Remove dead code exports from tokenMetadata.ts
- Create useFormSetValue hook to consolidate setValue wrapper pattern
- Standardize number formatting to use addCommasToNumber

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Resolved ABI conflict by taking v2 version

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Display an orange warning banner and update button text to inform users
when the relayer fails and they need to pay gas fees directly from their
wallet.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Expand the TangleMigration contract ABI to include all functions,
events, and error types. Add Base Sepolia chain icon for network
selection UI.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove attempt counter from the progress message to provide
a cleaner user experience during proof generation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Prefer on-chain data over indexer for pending unstake and withdraw requests
- Derive selectedAssetItem from depositedAssets in delegate page to ensure it updates when metadata loads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Renamed all unstake-related terminology to undelegate throughout the
restaking codebase for clearer naming. This includes renaming the
unstake directory, types, hooks, and variables.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Vaults tab was showing stale delegatedAmount values because
RestakeContext only fetched from the GraphQL indexer. This fix
adds useOnChainDelegator and merges its data with GraphQL,
using on-chain as source of truth for asset positions (same
pattern as useRestakingData used by Dashboard).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously clicking the delegate button on an operator would incorrectly
navigate to the deposit flow. Now it navigates to the delegate flow with
the operator pre-selected via query parameter.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
vutuanlinh2k2 and others added 3 commits December 30, 2025 09:38
Display the number of pending undelegate/withdraw requests on the expand
button to improve UX visibility. The badge only appears when there is at
least 1 request and stays in sync with the requests table data.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The useRestakingAssets and useRestakingAssetMap hooks were only using
wagmi's chainId, ignoring the network store. This caused the hooks to
not respond to chain changes via the UI when the user wasn't connected
to a wallet.

Now uses the same pattern as other hooks (useOperators, useDelegatorCount):
- When connected: use wagmi's chainId
- When not connected: use networkChainId from the store

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@vutuanlinh2k2 vutuanlinh2k2 changed the title QA fixes for restaking, liquid staking, and migration flows refactor(tangle-dapp): fixes for restaking, liquid staking, and migration flows Dec 30, 2025
@drewstone
Copy link
Contributor

@claude review

@claude
Copy link

claude bot commented Dec 30, 2025

Claude finished @drewstone's task —— View job


I'm reviewing this comprehensive PR covering restaking, liquid staking, and migration flow improvements.

Review Progress

  • Analyze project structure and key changes
  • Review restaking improvements (terminology, context updates, UI fixes)
  • Review liquid staking improvements (URL pre-selection, UI consistency, optimistic updates)
  • Review migration claim improvements (wallet mode banner, proof progress, ABI updates)
  • Review infrastructure changes (chain-aware metadata, Base Sepolia support, code cleanup)
  • Check for security issues and best practices
  • Verify adherence to project coding standards
  • Provide comprehensive feedback

🎯 Code Review Summary

This PR implements significant QA improvements across multiple domains with strong architectural decisions. The changes demonstrate good engineering practices with proper data flow management, consistent terminology, and user experience enhancements.

✅ Strengths

1. Excellent RestakeContext Architecture

The RestakeContext improvements in /libs/tangle-shared-ui/src/context/RestakeContext.tsx are well-designed:

  • Smart data merging: GraphQL for rich data + on-chain for accurate amounts (lines 175-192) solves the indexer staleness problem elegantly
  • Proper fallback strategy: Graceful degradation when indexer is unavailable
  • Comprehensive context hooks: Good separation of concerns with focused hooks like useRestakeAssetsFromContext
  • Debug logging: Helpful development aids without production bloat

2. Consistent Terminology Migration

The unstakeundelegate rename is thorough and maintains consistency:

  • File renames: /apps/tangle-dapp/src/pages/restake/undelegate/
  • Type updates: UndelegateRequest in /apps/tangle-dapp/src/types/restake.ts:1
  • Hook consistency: useUndelegateTx in /libs/tangle-shared-ui/src/data/tx/useUndelegateTx.ts

3. Smart Chain-Aware Infrastructure

The token metadata caching improvements prevent cross-chain collisions:

  • /libs/tangle-shared-ui/src/utils/fetchErc20TokenMetadata.ts:125-130: Chain ID used in cache keys
  • /libs/dapp-config/src/tokenMetadata.ts: Proper chain-specific address mappings
  • GraphQL hooks: Smart chain ID resolution when wallet disconnected (lines 284-285 in useDelegator.ts)

4. User Experience Enhancements

  • Request count badges: Clean implementation in /apps/tangle-dapp/src/pages/restake/ExpandTableButton.tsx:42-53
  • URL pre-selection: Liquid staking vault selection from URL params (lines 88-100 in deposit form)
  • Form utilities: useFormSetValue hook reduces code duplication and improves UX consistency

⚠️ Areas for Improvement

1. Error Handling in Migration Claims

In /apps/tangle-dapp/src/pages/claim/migration/index.tsx:32-82:

  • The parseTransactionError function is comprehensive but could benefit from structured error codes
  • Consider extracting to a shared utility if similar error parsing is needed elsewhere

2. Magic Numbers and Constants

Several hardcoded values could be extracted to constants:

  • /libs/tangle-shared-ui/src/context/RestakeContext.tsx:104: Chain IDs 84532 and 31337 for local dev detection
  • /libs/tangle-shared-ui/src/utils/fetchErc20TokenMetadata.ts:7: Default chain ID 1

3. Type Safety Concerns

  • Extensive use of as Address type assertions in GraphQL parsers (e.g., lines 220, 237 in useDelegator.ts)
  • Consider more robust address validation before casting

🔍 Security & Best Practices

Positive Security Practices:

  • ✅ Proper address validation with isAddress() checks
  • ✅ Chain ID validation in GraphQL hooks
  • ✅ Input sanitization in form handling
  • ✅ No hardcoded private keys or sensitive data

Minor Concerns:

  • Address lowercasing for normalization could be centralized in a utility function
  • ABI files show large diffs but appear to be auto-generated (acceptable)

📊 Code Quality Assessment

Architecture: 9/10

  • Excellent separation of concerns
  • Smart data flow design
  • Proper abstraction layers

Maintainability: 8/10

  • Good naming conventions
  • Consistent patterns
  • Could benefit from extracting some constants

Performance: 8/10

  • Efficient context usage with useMemo
  • Proper query optimization
  • Chain-aware caching prevents unnecessary calls

🚀 Recommendations

  1. Extract Constants: Move hardcoded chain IDs and default values to a constants file
  2. Error Handling: Consider creating a shared error parsing utility
  3. Type Safety: Add address validation helpers to reduce as Address usage
  4. Testing: Consider adding integration tests for the complex RestakeContext data merging logic

🎖️ Overall Assessment

Rating: Excellent (8.5/10)

This PR demonstrates high-quality engineering with thoughtful architectural decisions. The RestakeContext improvements are particularly well-designed, solving real data consistency issues. The consistent terminology migration and user experience enhancements show attention to detail. While there are minor opportunities for improvement, the overall implementation is solid and ready for production.

The changes align well with the project's coding standards from CLAUDE.md and follow React/TypeScript best practices throughout.


@vutuanlinh2k2 vutuanlinh2k2 self-assigned this Dec 30, 2025
@drewstone
Copy link
Contributor

drewstone commented Dec 30, 2025

You fixing anything else up here @vutuanlinh2k2 ?

@vutuanlinh2k2
Copy link
Contributor Author

You fixing anything else up here @vutuanlinh2k2 ?

No more pushes for this PR other minor fixes I can make based on Claude's suggestions.

I uploaded the demo video on Restaking on Slack

- Use EVMChainId enum instead of hardcoded chain IDs (84532, 31337, 1)
- Create shared parseTransactionError utility for user-friendly error messages
- Add safeParseAddress utilities to reduce unsafe `as Address` type assertions
- Update useDelegator to use address validation helpers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@drewstone drewstone merged commit 581fe9e into v2 Dec 30, 2025
1 check passed
@drewstone drewstone deleted the linh/qa/restaking-2 branch December 30, 2025 06:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants