Skip to content

Conversation

@zkSoju
Copy link

@zkSoju zkSoju commented Dec 14, 2025

Summary

  • Convert sequential context.get() calls to Promise.all() for parallel execution
  • Add balance floor (BigInt(0)) to prevent negative balances when indexer starts after token distribution
  • Skip creating negative balance records, log warning instead

Root Cause

Users who received HENLOCKED tokens before the indexer start block would get negative balances when they transferred tokens (e.g., to Beradrome staking). This caused "Locked Signal" mission verification to fail.

Changes

File Optimization
tracked-erc20.ts Parallel balance lookups + balance floor
tracked-erc721.ts Parallel holder adjustments
holder-stats.ts Parallel holder lookups + balance floor

Performance Impact

  • Before: 2 sequential DB reads per transfer event
  • After: 1 parallel DB read (2 queries in parallel) per transfer event

This reduces latency and improves indexer sync speed.

Testing

  • TypeScript compilation passes
  • Manual verification with affected user address

Related

  • Fixes ENG-4432
  • Session doc: cubquests-interface/docs/SESSION_2025_11_22_UNIFIED_HOLD_SYSTEM.md

🤖 Generated with Claude Code

zkSoju and others added 30 commits November 19, 2025 21:49
…erification

The Mibera NFT contract was configured under both TrackedErc721 and
MiberaStaking handlers, causing an Envio handler conflict where
TrackedHolder entries were never created. This broke hold-mibera
quest verification.

Changes:
- Remove MiberaStaking contract entry from config.yaml
- Add staking awareness to TrackedErc721 handler
- Staking deposits (user → PaddleFi/Jiko) no longer decrement tokenCount
- Users retain holder status while NFTs are staked
- MiberaStakedToken and MiberaStaker entities still created

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Merge remote Envio updates (v2.27.3 -> v2.32.2)
- Add HenloVault Mint event handler to capture initial HENLOCKED token distribution
- Maps strike values to HLKD token addresses for proper balance tracking
- Fixes negative balances caused by missing initial mint events

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

Co-Authored-By: Claude <noreply@anthropic.com>
Strike values are FDV targets in thousands, not raw numbers:
- 100000 = $100M FDV (not 100000000)
- 330000 = $330M FDV
- 420000 = $420M FDV
- 690000 = $690M FDV
- 1000000 = $1B FDV

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Remove duplicate HenloToken contract from config.yaml
- Merge burn tracking into TrackedErc20 handler with feature flags
- Add per-token configuration for burns and holder stats
- Create modular burn-tracking.ts and holder-stats.ts modules

Fixes issue where HENLO token in both HenloToken and TrackedErc20
handlers caused Envio to only process one, breaking burn indexing.

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Add 7 new HenloVault events (RoundOpened, RoundClosed, DepositsPaused,
  DepositsUnpaused, MintFromReservoir, Redeem, ReservoirSet)
- Add 6 new schema entities (HenloVaultRound, HenloVaultDeposit,
  HenloVaultBalance, HenloVaultEpoch, HenloVaultStats, HenloVaultUser)
- Implement 8 event handlers for complete vault system tracking
- Enables migration of Henlo interface from henlo-squid@v11 to Envio

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Add MiberaPremint handler for Participated/Refunded events on Berachain
- Add MiberaSets handler for ERC-1155 airdrop tracking on Optimism
  - Tracks transfers from distribution wallet as mints
  - Token IDs 8-11 = Strong Set, 12 = Super Set
- Add friend.tech handler for Trade events on Base
  - Filters for Mibera subjects (jani_key, charlotte_fang_key)
  - Tracks holder balances and subject stats
- Add burn detection to TrackedErc721 handler
  - Detects transfers to zero address and dead address
- Move Mibera Zora from Berachain to Optimism (correct chain)
- Add Zora collection key to tracked-erc721 constants

New schema entities:
- PremintParticipation, PremintRefund, PremintUser, PremintPhaseStats
- FriendtechTrade, FriendtechHolder, FriendtechSubjectStats

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Updated MiberaSets handler to track both mints and transfers
  - Mints: from zero address OR distribution wallet
  - Transfers: all other user-to-user movements
  - Records mint1155/transfer1155 actions with setTier context
- Added transfer tracking to TrackedErc721 handler
  - New TRANSFER_TRACKED_COLLECTIONS set for configurable tracking
  - Records transfer actions for mibera and mibera_zora collections
  - Tracks sender, recipient, tokenId for timeline/activity feeds

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

Co-Authored-By: Claude <noreply@anthropic.com>
…-721)

- Verified Mibera Zora contract (0x427a...) is ERC-1155 (Zora platform)
- Created new MiberaZora1155 contract definition in config.yaml
- Created mibera-zora.ts handler for TransferSingle/TransferBatch events
- Tracks mints (from zero address) and transfers (user-to-user)
- Removed mibera_zora from TrackedErc721 constants
- Added handler imports/exports to EventHandlers.ts

Collection types verified:
- mibera (0x6666...): ERC-721 (correct)
- mibera_sets (0x886d...): ERC-1155 (correct)
- mibera_zora (0x427a...): ERC-1155 (FIXED - was incorrectly ERC-721)

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Created src/lib/mint-detection.ts with shared utilities:
  - isMintFromZero(): Check if transfer is from zero address
  - isMintOrAirdrop(): Check zero OR airdrop wallets (for Sets)
  - isBurnAddress(): Check if destination is burn address
  - DEAD_ADDRESS constant

- Updated handlers to use shared utilities:
  - mibera-sets.ts: Uses isMintOrAirdrop with AIRDROP_WALLETS set
  - mibera-zora.ts: Uses isMintFromZero
  - mibera-collection.ts: Uses isMintFromZero, imports BERACHAIN_ID
  - tracked-erc721.ts: Uses isBurnAddress from shared lib

- Created src/handlers/friendtech/constants.ts:
  - MIBERA_SUBJECTS mapping (jani_key, charlotte_fang_key)
  - FRIENDTECH_COLLECTION_KEY constant

- Removed duplicate code:
  - Local ZERO_ADDRESS definitions (3 files)
  - Local isMint() functions (2 files)
  - Local isBurnAddress() function (1 file)
  - Local DEAD_ADDRESS constant (1 file)

Net reduction: 28 lines while improving maintainability.
No breaking changes - same logic, just centralized.

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Add NftBurn and NftBurnStats entities to schema
- Update Mibera handler to detect burns (transfers to zero/dead address)
- Add Milady collection handler for burn tracking on ETH mainnet
- Add Milady contract (0x5af0d9827e0c53e4799bb226655a1de152a425a5)
- Update ETH start block to 13090020 for Milady deployment

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

Co-Authored-By: Claude <noreply@anthropic.com>
Updated Optimism start_block from 121292097 to 125031052 to capture
all MiberaSets mints and airdrops from contract creation (Sept 6, 2024).

The indexer was missing initial mints from zero address to distribution
wallet and subsequent airdrops to users.

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Add Seaport v1.6 contract for secondary sales tracking
- Add MintActivity entity for unified activity feed
- Track PURCHASE activity type with royalty calculation
- Update MiberaCollection handler to create MintActivity on mints

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Add marketplace constants for Seaport addresses to detect secondary sales
- Flag secondary transfers in mibera-sets and tracked-erc721 handlers
  with isSecondary and viaMarketplace context fields
- Add PaddleFi lending protocol handlers:
  - Mint event: Track BERA supply by lenders (pToken minting)
  - Pawn event: Track NFT collateral deposits by borrowers
- Add PaddleSupply, PaddlePawn, PaddleSupplier, PaddleBorrower schema types
- Note: Beraji vault tracking removed (only captured fees, not actual supply)

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

Co-Authored-By: Claude <noreply@anthropic.com>
Expands marketplace detection from just Seaport to include:
- OpenSea/Seaport (5 addresses including Conduit)
- Blur (4 addresses including Blend)
- LooksRare (2 addresses)
- X2Y2 (2 addresses)
- Rarible (2 addresses)
- Foundation, SuperRare, Zora, NFTX, Sudoswap
- Gem/Genie aggregators

This enables proper viaMarketplace flag detection for ERC-721 and ERC-1155
transfers at the indexer level.

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

Co-Authored-By: Claude <noreply@anthropic.com>
The address 0x886d2176d899796cd1affa07eff07b9b2b80f1be is the Berachain
Honeycomb ERC721 contract, not CubBadges1155. Having it listed under
CubBadges1155 caused Envio to listen for ERC1155 events instead of
ERC721 Transfer events, so Berachain Honeycomb transfers were never indexed.

This fixes the indexer to properly track ~11,416 bridged Honeycomb NFTs
on Berachain.

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

Co-Authored-By: Claude <noreply@anthropic.com>
The Mint and MintFromReservoir handlers were hardcoding epochId as 0
when looking up rounds, but actual rounds have epochIds 1-6 based on
strike value. This caused totalDeposits to never be updated since the
rounds weren't found.

Added STRIKE_TO_EPOCH mapping and findRoundByStrike helper to correctly
locate rounds when processing deposit events.

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

Co-Authored-By: Claude <noreply@anthropic.com>
The 20000 strike (campaign rewards) was missing from the token mapping,
causing all Mint events for that strike to be skipped. Added the token
address 0x4c9c76d10b1fa7d8f93ba54ab48e890ff0a7660d.

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

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

Co-Authored-By: Claude <noreply@anthropic.com>
- Add STRATEGY_TO_MULTI_REWARDS lookup table for known strategy->multiRewards mappings
- Fall back to hardcoded values when RPC call fails (e.g., contract doesn't exist at historical block)
- Use ENVIO_RPC_URL consistently in both effect and contractRegister
- Check hardcoded mapping first in contractRegister for faster/more reliable lookups

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

Co-Authored-By: Claude <noreply@anthropic.com>
…balances

- Convert sequential context.get() calls to Promise.all() for parallel execution
- Add balance floor (BigInt(0)) to prevent negative balances when indexer
  starts after token distribution
- Skip creating negative balance records, log warning instead
- Optimized files:
  - tracked-erc20.ts: Parallel balance lookups
  - tracked-erc721.ts: Parallel holder adjustments
  - holder-stats.ts: Parallel holder lookups + balance floor

This improves sync performance and fixes the root cause of "Locked Signal"
mission verification failures for users who had HENLOCKED tokens before
indexer started.

Closes ENG-4432

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove direct RPC call in StrategyUpdated.contractRegister
- Use hardcoded STRATEGY_TO_MULTI_REWARDS mapping instead
- Add fast-path in handler to check mapping before Effect API
- Log warning for unknown strategies instead of blocking on RPC

This eliminates RPC latency during indexing. When deploying new strategies,
add the strategy -> multiRewards mapping to STRATEGY_TO_MULTI_REWARDS.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The StrategyUpdated event only fires when strategies change,
which is infrequent. The RPC call overhead is negligible for
rare events, and maintaining RPC fallback ensures we don't
miss indexing new strategies not in the hardcoded mapping.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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