Skip to content

feat: Mezo Lens integration (Stack / Borrow / Save / Lock / Swap / Liquidity) + chain-aware EDB bridge - #21

Open
Timidan wants to merge 18 commits into
masterfrom
feat/mezo
Open

feat: Mezo Lens integration (Stack / Borrow / Save / Lock / Swap / Liquidity) + chain-aware EDB bridge#21
Timidan wants to merge 18 commits into
masterfrom
feat/mezo

Conversation

@Timidan

Copy link
Copy Markdown
Owner

Summary

  • Adds Mezo Lens — six purpose-built tabs (Stack, Borrow, Save, Lock, Swap, Liquidity) that let a user preview every leg of a Mezo position before signing. All flows run through atomic eth_simulateV1 bundles so the user sees the resulting trove, ICR, LP tokens, swap quote, etc. before any wallet write.
  • Chain-aware EDB bridge routing — the dev/Vercel proxy inspects chainId per request and forwards Mezo (31611/31612) to a dedicated bridge while keeping every other chain on the existing bridge. Two new env vars (EDB_DEFAULT_BRIDGE_URL, EDB_MEZO_BRIDGE_URL) make the split explicit.
  • Simulation trace upgrades — native token symbol now reflects the replayed chain (BTC on Mezo, not "ETH"), Blockscout-vs-Sourcify badge renders correctly, native movements collapse to net-per-address, event dedup honors call-frame + emission index so legitimate identical logs from a bulk-transfer loop stay distinct.
  • Mezo bridge (edb submodule, separate PR) — stateful MEZO precompile inspector tracks balance deltas + allowances so contracts using before/after balance math (Wormhole NTT, Aerodrome) replay correctly. Chain metadata registered for both networks.

What ships in each commit

  • e27f0e7 chain config (registry, contracts, CSP, env docs)
  • 1b2148a chain-aware bridge routing (api/edbShared.ts, vite proxy, Vercel proxy)
  • 632f87c Mezo Lens app (46 files, all under src/components/integrations/mezo/)
  • 1bb6c4e trace + Blockscout badge + token movement net-per-address
  • d5407dd SimulationHistory IDB v2 → v3 migration
  • 05a7981 LI.FI Earn drive-by type tightening
  • dac6ec8 nav, search, og tags, logos, public mezo-lab
  • d685a4a edb submodule pointer bump

Test plan

  • Vercel preview deploys from feat/mezo; /integrations/mezo loads, wallet switch targets chain 31611
  • Stack: 0.04 BTC + 2000 MUSD + 50 sMUSD + 50 MEZO lock → all 5 plan steps green; "you'll deposit / you'll receive" shows BTC + MEZO out, sMUSD + veMEZO in
  • Borrow: open a standalone trove → ICR + liquidation price in receive panel
  • Save: deposit existing MUSD into sMUSD → sMUSD in receive
  • Lock: lock MEZO standalone → veMEZO NFT in receive (14-day default avoids week-boundary edge case)
  • Swap: quote BTC → MUSD on volatile pool, slippage selector flows to signing min-out (no 0-min-out signing)
  • Liquidity: add BTC/MUSD volatile pair, "you'll receive" shows LP tokens + pool share
  • Transaction Utils → Simulation (EDB) → replay Mezo mainnet 0x75b67f493f482ac707309bd55c0e4979e3fc1ca69d13be6b1889b27846f7351f:
    • SUCCESS status
    • Asset column shows "BTC" not "ETH"
    • Contracts panel shows "BLOCKSCOUT" badges
    • Events tab includes the MEZO precompile Transfer event
    • No duplicate events
    • Native token movements collapse to net-per-address
  • Replay an Ethereum mainnet tx through the same UI to confirm non-Mezo routing still works
  • Vercel env vars set per scope:
    • EDB_API_KEY (production, preview, development)
    • EDB_DEFAULT_BRIDGE_URL=https://edb.hexkit.tech (all scopes)
    • EDB_MEZO_BRIDGE_URL=https://edb.hexkit.tech/mezo (all scopes)
    • ETHERSCAN_API_KEY (all scopes)
    • VITE_WALLETCONNECT_PROJECT_ID (all scopes)

Companion PR

  • Timidan/edb-extendedfeat/mezo branch — Mezo chain_metadata + stateful precompile inspector + source-provider tagging

Timidan added 9 commits May 23, 2026 05:37
…ute handling
- Added intentsApi.ts for handling intents-related API calls.
- Introduced useIntentOrderStatus.ts for managing intent order status with React Query.
- Created withdrawComposerRoute.ts to manage the withdrawal process through composer routes.
- Enhanced error handling and user feedback during the withdrawal process.
- Updated earnApi.ts to separate quote URL building from fetching logic.
- Improved type definitions in types.ts and added nullable symbol handling for EarnToken.
- Implemented nonce generation for unique order identification in nonce.ts.
- Added deadline management for orders in deadlines.ts.
- Created standardOrder.ts for building and managing standard order structures.
- Updated Vercel and Vite configurations to support new API endpoints.
- Add canonical contract addresses (MUSD, MEZO precompile, BTC ERC-20 surface,
sMUSD, BorrowerOperations, TroveManager, SortedTroves, HintHelpers, PriceFeed,
veMEZO, Voter, PoolFactory, Router, plus pool helpers)
- Extend chain registry with both networks (native BTC, 18 decimals)
- Extend CSP connect-src to allow Mezo public RPCs + Blockscout APIs
- Document EDB_DEFAULT_BRIDGE_URL and EDB_MEZO_BRIDGE_URL env vars
The dev/Vercel proxy now inspects the chainId on every request (from the
?chainId query param or the JSON body) and forwards to a Mezo bridge for
chain 31611/31612 vs the default bridge for everything else. Two new env
vars let operators point each side at a different URL; without them, the
proxy auto-derives the Mezo URL by appending /mezo to EDB_BRIDGE_URL.
- New api/edbShared.ts module exports resolveEdbBridgeUrl(),
extractChainIdFromRawJsonBody(), and ETHERSCAN key injection helpers
- vite.config.ts dev proxy uses the shared helpers; the old static target
is replaced with a per-request configure() that picks the bridge live
- api/edb-proxy.ts (Vercel) mirrors the dev path so previews route the
same way as production
- vercel.json adds the /mezo Blockscout rewrite alongside the testnet one
- DebugBridgeService and useDebugPrep pass the chainId through to the
bridge calls
…uidity)
End-to-end integration for Mezo Testnet that lets a user preview every leg
of a Mezo position before signing. Six tabs share a common workbench:
input + atomic-bundle eth_simulateV1 preview + step-by-step pipeline.
Highlights:
- sim/ — eth_simulateV1 client with per-leg gas budgeting (5M for openTrove,
2M for veMEZO.createLock and Router.addLiquidity, 1M+ default split for
the rest); bundle builders for each tab; viewcall encoders/decoders;
unified SimulationResult shape with trove / swap / liquidity / veMEZO
outcome fields
- pipeline/ — wagmi-backed execution after sim succeeds; per-leg status
timeline with retry; legHandlers translate MezoLegSpec to wagmi writes
- preview/ — DepositReceiveCards / DecodedLegList / TokensMovedPanel;
PreviewPanel composes them and renders the atomic-flow summary
- tabs/ — six tabs, each fronting one bundle builder. Common UX:
AssetInput with `intent="deposit"|"receive"`, pool / slippage controls,
pre-sim ICR validation, post-sim "you'll deposit / you'll receive" cards
- abi/ — minimal ABI fragments for MUSD, sMUSD, BorrowerOperations,
TroveManager, PriceFeed, HintHelpers, SortedTroves, VotingEscrow,
Voter, Gauge, Pool, Router (4-field Aerodrome routes), PoolFactory
- hooks/ — useFindPool, useReserves, usePriceFeed via wagmi
- components/ — AssetInput, AssetIcon, TabBar, MezoTopBar, WorkbenchBody,
FlowRibbon, SectionEyebrow, Term (glossary popovers)
- ChainGate gates the whole page on wallet + chain 31611
- copy.ts holds every user-facing string (no jargon)
- MezoLensPage routes between tabs and renders PositionsSidebar +
HonestyFooter alongside
The simulation-results renderer now adapts to the replayed chain instead
of hardcoding Ethereum assumptions, and the Contracts panel honors the
provider that actually returned the source.
- edbTraceConverter accepts optional nativeSymbol / nativeName so native
movements render as BTC on Mezo (chain id 31611/31612) instead of ETH
- Event dedup key now folds in the call-frame id + emission index so
legitimate identical logs from a loop (bulk Transfer airdrops, etc.)
don't collapse to a single row; same fix mirrored in the engine renderer
- Native token movements collapse to net-per-address rows so a multi-hop
value-passing tx surfaces one debit + one credit instead of every
intermediate frame
- Contracts panel displays a "BLOCKSCOUT" / "SOURCIFY" badge based on the
explicit sourceProvider tag the engine attaches to each artifact, with
bridge compaction preserving the label end-to-end
- Token metadata cache seeds MEZO, BTC, MUSD, sMUSD so a synthetic
MEZO precompile Transfer renders as "MEZO" instead of "MEZOCaller"
- Bridge response normalization now plumbs sourceProvider through
artifactFetching, responseParsing, bridgeSimulation, and the trace
compactor scripts
Idempotent onupgradeneeded migration ensures the meta + simulations
stores have every needed index (timestamp, status, networkId,
contractAddress, from, to, functionName) on both fresh installs and
upgrades from v1/v2 without dropping existing entries.
- Adds version-change handler so a second tab triggers a clean reopen
- Refines SimulationHistoryPage retry path so a stale DB connection no
longer wedges the "Failed to load" state
Drive-by cleanup encountered while building Mezo Lens — the touched
files are unrelated paths that benefited from minor type tightening
and removal of dead conditional branches. Behavior unchanged.
- Add Mezo Lens entries to top nav, mobile drawer, integrations hub, and
universal search so the new flow is discoverable
- Route meta tags for /integrations/mezo (title, description, og)
- Mezo logo + wordmark assets
- public/mezo-lab/ standalone preview page used during prototyping
- README documents the new integration
- Drop a trailing-newline-only .gitignore tweak
Pulls in chain metadata for Mezo Testnet + Mainnet, the stateful
MEZO precompile inspector (balanceOf delta tracking + allowance
defaults), source-provider tagging on artifacts, event dedup,
and synthetic precompile log emission. See edb commit f280d32.
CopilotAI review requested due to automatic review settings May 24, 2026 20:27
@vercel

vercelBot commented May 24, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
web3-toolkitReadyReadyPreview, CommentMay 25, 2026 12:47am

@chatgpt-codex-connectorchatgpt-codex-connectorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit:d685a4a382

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +244 to +248
].filter((event, index, allEvents) => {
const key = eventKey(event, index);
return allEvents.findIndex((candidate, candidateIndex) =>
eventKey(candidate, candidateIndex) === key
) === index;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve duplicate logs when merging event sources

The sourceEvents dedup step collapses events using only address|topics|data, so two real logs with identical payloads (e.g., repeated Transfer emissions in loops or across call frames) are merged into one. This regresses event accuracy in the Events tab by undercounting legitimate emissions and hides execution details users rely on for simulation review. Include a stable per-emission discriminator (such as call-frame id + in-frame index or txHash/logIndex when present) in the key to avoid dropping valid duplicates.

Useful? React with 👍 / 👎.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a Mezo-specific “Lens” integration (Stack/Borrow/Save/Lock/Swap/Liquidity) with atomic eth_simulateV1 bundle previews, and updates the EDB/proxy + trace parsing pipeline to be chain-aware (notably for Mezo mainnet/testnet) with improved source-provider tagging, event handling, and native asset rendering.

Changes:

  • Add Mezo Lens UI + simulation bundle builder infrastructure for multi-step position previews.
  • Route EDB bridge requests to different upstream bridges based on chainId (Mezo vs non-Mezo), and extend Blockscout/Sourcify/Etherscan source-provider handling.
  • Improve trace parsing/output (native symbol/name, event dedupe strategy, net native movements per address) and migrate SimulationHistory IDB schema v2 → v3.

Reviewed changes

Copilot reviewed 120 out of 123 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
vercel.jsonAdds Mezo Blockscout proxy routes and LI.FI intents API routing on Vercel.
src/utils/transaction-simulation/responseParsing.tsImproves source provider detection for contract artifacts (explicit provider fields + meta fallbacks).
src/utils/transaction-simulation/bridgeSimulation.tsPreserves sourceProvider when inlining artifacts from bridge responses.
src/utils/transaction-simulation/artifactFetching.tsAdds Mezo chainIds to Blockscout instance mapping.
src/utils/tokenMovements.tsSeeds token metadata for Mezo assets (MEZO/BTC/MUSD/sMUSD).
src/utils/simulationArtifacts.tsMakes EDB trace conversion chain-aware for native asset name/symbol.
src/utils/resolver/sources/blockscout.tsMakes Blockscout URL construction robust across /api, /api/v2, and proxy bases; adds Mezo proxy mapping.
src/utils/edbTraceConverter.tsAdds native asset overrides, event dedupe keyed by call-frame + emission index, and collapses native movements to net deltas per address.
src/services/SimulationHistoryService.tsBumps IndexedDB version to v3, hardens upgrade/index creation, and improves filtering null-safety.
src/services/DebugBridgeService.tsUpdates debug bridge behavior to support new chain-aware routing/simulation behavior.
src/lib/intents/standardOrder.tsAdds intent order modeling utilities for LI.FI intents.
src/lib/intents/nonce.tsAdds nonce helpers for intent signing/validation.
src/lib/intents/eip7930.tsAdds EIP-7930 related helpers for intent formats.
src/lib/intents/deadlines.tsAdds deadline utilities for intent payloads.
src/lib/intents/contracts.tsAdds contract-related helpers for intents.
src/lib/intents/addressBytes.tsAdds address/bytes encoding helpers for intents.
src/hooks/useUniversalSearch.tsExtends search to include Mezo-related navigation/content updates.
src/contexts/debug/useDebugPrep.tsUpdates debug preparation flow to support new simulation/routing behavior.
src/components/SimulationHistoryPage.tsxUpdates simulation history UI to reflect IDB schema changes and new fields.
src/components/simulation-results/useSimulationPageState.tsUpdates simulation page state management for new artifacts/trace behavior.
src/components/simulation-results/SummaryTab.tsxUpdates summary rendering for revised asset movement/native symbol behavior.
src/components/simulation-results/EventsTab.tsxUpdates events table behavior consistent with improved dedupe/topics handling.
src/components/simulation-results/eventDecoder.tsUpdates event decoding pipeline to align with new trace/artifact fields.
src/components/simulation-results/ContractsTab.tsxUpdates contract verification/source-provider badges (Blockscout vs Sourcify vs Etherscan).
src/components/shared/RouteMetaTags.tsxAdds/updates OG/meta tags for Mezo integration pages.
src/components/Navigation.tsxAdds Mezo navigation entries and related routing.
src/components/MobileDrawer.tsxEnsures Mezo navigation works in mobile drawer.
src/components/integrations/mezo/tabs/SaveTab.tsxAdds Mezo Lens “Save” tab UI and simulation wiring.
src/components/integrations/mezo/TabBar.tsxAdds Mezo Lens tab navigation component.
src/components/integrations/mezo/sim/views.tsAdds read-only view calls used in Mezo bundle simulations.
src/components/integrations/mezo/sim/types.tsAdds shared types for Mezo simulation legs/views/results.
src/components/integrations/mezo/sim/ethSimulateV1.tsImplements atomic bundle simulation builder for Mezo flows.
src/components/integrations/mezo/sim/bundles/swap.tsAdds swap bundle legs/views for Mezo Lens.
src/components/integrations/mezo/sim/bundles/stack.tsAdds stack bundle legs/views for Mezo Lens.
src/components/integrations/mezo/sim/bundles/save.tsAdds save bundle legs/views for Mezo Lens.
src/components/integrations/mezo/sim/bundles/lock.tsAdds lock bundle legs/views for Mezo Lens.
src/components/integrations/mezo/sim/bundles/liquidity.tsAdds liquidity bundle legs/views for Mezo Lens.
src/components/integrations/mezo/sim/bundles/borrow.tsAdds borrow bundle legs/views for Mezo Lens.
src/components/integrations/mezo/sim/buildCalls.tsAdds shared call construction helpers for Mezo bundles.
src/components/integrations/mezo/preview/PreviewPanel.tsxAdds Mezo plan preview panel for all bundle legs.
src/components/integrations/mezo/preview/DecodedLegList.tsxAdds decoded leg rendering for preview UX.
src/components/integrations/mezo/PositionsSidebar.tsxAdds positions sidebar for Mezo Lens layouts.
src/components/integrations/mezo/pipeline/useMezoLegPipeline.tsAdds leg pipeline orchestration for Mezo plan building/simulation.
src/components/integrations/mezo/pipeline/MezoLegTimeline.tsxAdds timeline UI for leg execution/simulation steps.
src/components/integrations/mezo/pipeline/mezoLegs.tsDefines Mezo leg models and composition rules.
src/components/integrations/mezo/pipeline/legHandlers.tsImplements per-leg decoding/formatting/handling logic.
src/components/integrations/mezo/MezoLensPage.tsxAdds Mezo Lens top-level page routing + tab layout.
src/components/integrations/mezo/index.tsExposes Mezo integration entrypoint(s).
src/components/integrations/mezo/hooks/useReserves.tsAdds Mezo pool reserve querying hook(s).
src/components/integrations/mezo/hooks/usePriceFeed.tsAdds Mezo price feed querying hook(s).
src/components/integrations/mezo/hooks/useFindPool.tsAdds Mezo pool discovery hook(s).
src/components/integrations/mezo/HonestyFooter.tsxAdds Mezo Lens disclosure/footer component.
src/components/integrations/mezo/glossary.tsAdds Mezo glossary terms for UI help text.
src/components/integrations/mezo/copy.tsAdds Mezo-specific copy strings.
src/components/integrations/mezo/constants.tsAdds Mezo chain constants/addresses for simulations.
src/components/integrations/mezo/components/WorkbenchBody.tsxAdds shared layout for Mezo Lens workbench.
src/components/integrations/mezo/components/Term.tsxAdds term/help UI component(s) for Mezo Lens.
src/components/integrations/mezo/components/SectionEyebrow.tsxAdds section heading UI component(s).
src/components/integrations/mezo/components/MezoTopBar.tsxAdds Mezo Lens top bar UI.
src/components/integrations/mezo/components/FlowRibbon.tsxAdds flow/status ribbon UI for Mezo Lens.
src/components/integrations/mezo/components/AssetInput.tsxAdds Mezo-specific asset input component(s).
src/components/integrations/mezo/ChainGate.tsxGates Mezo Lens UX by selected chain.
src/components/integrations/lifi-earn/VaultList.tsxUpdates LI.FI Earn UI to support intents-driven behaviors.
src/components/integrations/lifi-earn/useIntentOrderStatus.tsAdds hook for tracking intent order status.
src/components/integrations/lifi-earn/types.tsTightens types related to LI.FI Earn / intents.
src/components/integrations/lifi-earn/txUtils.tsUpdates tx utils for intent-based flows.
src/components/integrations/lifi-earn/TokenIcon.tsxUpdates token icon handling for Earn/intents flows.
src/components/integrations/lifi-earn/intentsApi.tsAdds client API wrapper for intents endpoint.
src/components/integrations/lifi-earn/hooks/useWithdrawQuote.tsUpdates withdraw quoting to support intents semantics.
src/components/integrations/lifi-earn/earnApi.tsUpdates Earn API client behavior/types.
src/components/integrations/lifi-earn/destinationTokenOptions.tsAdds destination token option logic for Earn flows.
src/components/integrations/lifi-earn/concierge/VaultRecommendations.tsxUpdates concierge recommendations for intents support.
src/components/integrations/lifi-earn/concierge/types.tsUpdates concierge types to reflect new intent structures.
src/components/integrations/lifi-earn/concierge/LlmErrorAlert.tsxUpdates LLM error UX for concierge flows.
src/components/integrations/lifi-earn/concierge/intent/intentLegs.tsAdds intent-based leg generation / degradation logic.
src/components/integrations/lifi-earn/concierge/intent/hooks/useVaultsByIntent.tsUpdates vault fetching to support intents.
src/components/integrations/lifi-earn/concierge/intent/hooks/useIntentRecommendation.tsUpdates intent recommendation logic.
src/components/integrations/lifi-earn/concierge/IdleSweepPanel.tsxUpdates Idle Sweep UI for updated flows.
src/components/integrations/lifi-earn/concierge/FlowDiagram.tsxUpdates concierge flow diagram for new leg types.
src/components/integrations/lifi-earn/concierge/fallback.tsUpdates concierge fallback behavior with intents integration.
src/components/integrations/IntegrationsHub.tsxAdds Mezo integration entry to the integrations hub.
src/components/ExecutionStackTrace.tsxUpdates execution stack trace UI consistent with new simulation artifacts.
src/chains/registry.tsRegisters Mezo chain metadata (native currency symbol/name) and related chain config.
scripts/trace-processing.mjsUpdates trace processing script for new trace/artifact behaviors.
scripts/simulator-bridge.mjsUpdates simulator bridge script to support chain-aware routing.
scripts/artifact-compactor.mjsUpdates artifact compaction script for new artifact shapes/source providers.
README.mdDocuments new env vars, Mezo integration, and updated simulation/bridge behavior.
public/logos/mezo.svgAdds Mezo logo asset.
public/logos/mezo-wordmark.svgAdds Mezo wordmark asset.
index.htmlUpdates metadata/links for Mezo and updated routing.
data/mezoContracts.tsAdds Mezo contract registry/constants used by the Lens.
api/lifi-intents.tsAdds serverless API proxy for LI.FI intents (including rate limiting).
api/edbShared.tsAdds shared chainId extraction and bridge URL resolution helpers.
api/edb-proxy.tsImplements chain-aware EDB bridge routing and streaming/non-streaming behaviors.
.gitignoreUpdates ignores for new artifacts/assets.
.env.exampleDocuments new env vars (EDB_DEFAULT_BRIDGE_URL, EDB_MEZO_BRIDGE_URL, etc.).
.codegraph/.gitignoreAdds ignore rules for codegraph outputs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadapi/edb-proxy.ts
Comment on lines 174 to 180
if (isSSE) {
// Abort upstream when client disconnects
req.on("close", () => controller.abort());
} else {
// Regular requests get a hard timeout
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
req.on("close", () => clearTimeout(timer));
timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
}
Comment on lines +92 to +100
const remainingBudget =
BUNDLE_GAS_BUDGET > reservedGas ? BUNDLE_GAS_BUDGET - reservedGas : 0n;
const share =
callsNeedingDefault > 0n ? remainingBudget / callsNeedingDefault : 0n;
const perCallDefault = share < MIN_CALL_GAS ? MIN_CALL_GAS : share;
const defaultGas = `0x${perCallDefault.toString(16)}` as Hex;
const callsWithGas: SimCall[] = blockStateCall.calls.map((call) =>
call.gas ? call : { ...call, gas: defaultGas },
);
Comment threadapi/lifi-intents.ts
Comment on lines +32 to +52
// Best-effort per-IP rate limit (resets on cold start). Friction, not auth.
const RATE_LIMIT_WINDOW_MS = 60_000;
const RATE_LIMIT_MAX = 120;
const rateBuckets = new Map<string, { count: number; resetAt: number }>();

function rateLimit(req: VercelRequest): boolean {
const fwd = req.headers["x-forwarded-for"];
const ip = (Array.isArray(fwd) ? fwd[0] : fwd ?? req.socket?.remoteAddress ?? "")
.toString()
.split(",")[0]
.trim();
if (!ip) return true; // can't identify caller — let it through, upstream will protect
const now = Date.now();
const slot = rateBuckets.get(ip);
if (!slot || slot.resetAt < now) {
rateBuckets.set(ip, { count: 1, resetAt: now + RATE_LIMIT_WINDOW_MS });
return true;
}
if (slot.count >= RATE_LIMIT_MAX) return false;
slot.count += 1;
return true;
Mezo's Router only exposes swapExactTokensForTokens and addLiquidity —
there is no ETH-native variant because BTC on Mezo is itself an ERC-20
surface (0x7b7C…0000). The swap and liquidity bundles already always
use the standard token-token entrypoints; the routerSwapEthIn /
routerSwapEthOut / routerAddLiquidityEth leg types were dead and broke
the strict wagmi v2 typing on Vercel.
Removes those leg types from MezoLegSpec and their orphan branches in
buildCalls.ts, legHandlers.ts, decodeResults.ts, and the swap/liquidity
type-guards. Casts the routerSwap routes arg to `never` so wagmi's
strict `as const` ABI inference stops widening to the runtime tuple.
The SimulationResultsPage Summary header (Value + Tx Fee fields) was
rendering "ETH" for every replay regardless of chain. A Mezo Mainnet
tx with 0.000001 BTC value showed "0.000001 ETH" + "0 ETH" because
formatEth + calculateTxFee hardcoded the suffix and computeGasValues
seeded txFee = "0 ETH" literal.
- formatters.formatEth(wei, symbol = "ETH") + calculateTxFee(...,
symbol = "ETH") now accept the native symbol with a back-compat
default so existing call sites keep working.
- gasHelpers.computeGasValues(..., nativeSymbol = "ETH") threads it
into the txFee placeholder.
- SimulationResultsPage resolves nativeSymbol via getChainById(
result.chainId ?? contractContext.networkId)?.nativeCurrency.symbol
and forwards it to both computeGasValues and TransactionSummary.
- TransactionSummary adds an optional nativeSymbol prop and uses it
in the Value field rendering.
NATIVE TOKEN CHANGE table was already chain-aware via the trace
converter; this just brings the Summary header into line.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 124 out of 127 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

src/services/SimulationHistoryService.ts:252

  • request.onblocked immediately rejects initPromise, but the open request may later unblock and still fire onsuccess, setting this.db after the promise has rejected. That can leave the service in a partially-initialized state and force callers into error handling even though the DB eventually opened. Consider tracking a “blocked” flag to ignore a later onsuccess, or (preferably) surface a blocked state to the UI while keeping the init promise pending until the upgrade either succeeds or errors.

Comment on lines +240 to +249
const sourceEvents = [
...traceEvents,
...rawTraceEvents,
...(Array.isArray(artifacts?.events) ? artifacts.events : []),
].filter((event, index, allEvents) => {
const key = eventKey(event, index);
return allEvents.findIndex((candidate, candidateIndex) =>
eventKey(candidate, candidateIndex) === key
) === index;
});
Comment threadapi/edb-proxy.ts
Comment on lines 174 to 178
if (isSSE) {
// Abort upstream when client disconnects
req.on("close", () => controller.abort());
} else {
// Regular requests get a hard timeout
Comment on lines +25 to +29
const tokenA = toMezoPoolTokenAddress(p.tokenA);
const tokenB = toMezoPoolTokenAddress(p.tokenB);

if (sameAddress(tokenA, tokenB)) {
throw new Error("buildLiquidityBundle: tokenA and tokenB must differ");
Wire MEZO, BTC, and MUSD icons through CoinGecko so the trace ASSET
column and Mezo Lens AssetIcon stop falling back to a generic dot.
Covers both the Mezo precompile/surface addresses and the Ethereum
NTT bridge twins. sMUSD has no public CDN entry so it keeps a
bundled SVG.
veBTC is the base ve-token of Mezo's Aerodrome v2 fork; add it as
an AssetSymbol with a local orange glyph + glossary entry. Bridged
USDC/USDT are indexed by CoinGecko, so route them through the same
CDN map as MUSD/MEZO. Seed metadata so traces surface the correct
symbol without an RPC roundtrip.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 125 out of 129 changed files in this pull request and generated 4 comments.

Comment on lines +25 to +54
const tokenA = toMezoPoolTokenAddress(p.tokenA);
const tokenB = toMezoPoolTokenAddress(p.tokenB);

if (sameAddress(tokenA, tokenB)) {
throw new Error("buildLiquidityBundle: tokenA and tokenB must differ");
}

// Mezo's Router has no `addLiquidityETH` — BTC on Mezo is the ERC-20
// surface at 0x7b7C…0000, so we always approve+addLiquidity. Same
// pattern as the swap builder.
const legs: MezoLegSpec[] = [
{
type: "approveErc20",
token: p.tokenA,
spender: MEZO_CONTRACTS.Router,
amount: p.amountADesired,
tokenLabel: tokenLabel(p.tokenA),
},
{
type: "approveErc20",
token: p.tokenB,
spender: MEZO_CONTRACTS.Router,
amount: p.amountBDesired,
tokenLabel: tokenLabel(p.tokenB),
},
{
type: "routerAddLiquidity",
tokenA: p.tokenA,
tokenB: p.tokenB,
stable: p.stable,
Comment on lines +240 to +249
const sourceEvents = [
...traceEvents,
...rawTraceEvents,
...(Array.isArray(artifacts?.events) ? artifacts.events : []),
].filter((event, index, allEvents) => {
const key = eventKey(event, index);
return allEvents.findIndex((candidate, candidateIndex) =>
eventKey(candidate, candidateIndex) === key
) === index;
});
Comment threadapi/edb-proxy.ts
Comment on lines +156 to +159
const parsedQueryChainId = queryChainId ? Number(queryChainId) : null;
const chainId = Number.isInteger(parsedQueryChainId)
? parsedQueryChainId
: extractChainIdFromRawJsonBody(rawBody, req.headers["content-type"]);
Comment on lines +10 to +14
export function nextOrderNonce(): bigint {
counter = (counter + 1) & 0xffff;
const ts = BigInt(Date.now());
const rand = BigInt(Math.floor(Math.random() * 0xffffffff));
return (ts << (RAND_BITS + COUNTER_BITS)) | (rand << COUNTER_BITS) | BigInt(counter);
Three Stack-tab fixes that surface during recording:
1. Side-rail Trove and veMEZO sections were placeholder text. Wire
them to TroveManager.Troves and veMEZO.locked so they reflect the
wallet's actual on-chain position with 6s refetch.
2. If the user already has an active trove (status === 1), the Stack
bundle now omits the openTrove leg instead of replaying it. Saves
the user from a guaranteed revert when they re-run Build Stack.
3. Pipeline executeAll now skips legs already in "confirmed" state so
clicking Build Stack again resumes from the first non-confirmed
step. Pair with a 90s timeout on the wagmi receipt wait so a stuck
poll can't halt the whole stack indefinitely.
Side-rail Trove row is now a button that opens a Manage Trove dialog
with two modes:
- Adjust — single signed adjustTrove call combining BTC delta
(+ add / − withdraw) and MUSD delta (+ borrow / − repay). When
repaying, the bundle prepends a MUSD approve so BorrowerOperations
can pull the repayment.
- Close — approve current debt + closeTrove. Burns the trove,
refunds the 200 MUSD gas comp, returns all collateral. Blocks the
button when wallet MUSD is short of the debt.
Both flows reuse useMezoBundleSimulation for the live preview and
useMezoLegPipeline for execution, matching the rest of Mezo Lens.
Implement the previously-stubbed repayMUSD and closeTrove handlers.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Execution handlers were wired in the previous commit but the
simulation-side encoder still threw "v2 leg not implemented",
so the Manage Trove preview failed before the user could sign.
Encode both as plain BorrowerOperations calls; the trove dialog
now runs through the sim path cleanly.
Liquity-fork closeTrove pulls (debt - GAS_COMPENSATION) from the
user's wallet. The 200 MUSD gas comp lives in the protocol's Gas
Pool throughout the trove's life and is burned automatically on
clean close — never the borrower's cost. The earlier approve sized
to the full debt and the dialog warning said the user was "short by"
the gas comp amount, both wrong.

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Side-rail now surfaces every position (Trove, veMEZO, sMUSD savings,
MUSD/BTC LP) and each row opens a dedicated Manage dialog. When a
position is empty, the row shows a "Deposit →" / "Add →" prompt so
the user can open one without leaving the rail.
- ManageLockDialog: top up MEZO into the existing veMEZO position
(approve + increaseAmount) or extend the unlock time. Extend passes
a relative duration from now (Aerodrome VotingEscrow semantics),
not an absolute timestamp.
- ManageSavingsDialog: deposit MUSD into sMUSD or withdraw MUSD from
the vault (the vault burns the matching sMUSD shares).
- ManageLiquidityDialog: add MUSD/BTC liquidity or remove LP shares.
Carries a testnet banner — slippage min is 0 and the dialog should
not ship to mainnet without slippage controls.
Supporting work:
- Wire sMusdWithdraw + routerRemoveLiquidity (sim encoder + exec
handler + decoded summary + Router ABI entry).
- Shared BalanceDeltaPreview surfaces concrete asset deltas (wallet
BTC / MUSD / sMUSD / MEZO + trove debt/coll + LP + veMEZO lock)
from the simulation outcome.
- Close-trove approve sized off principal+interestOwed (total debt)
minus the 200 MUSD gas comp — the protocol's Gas Pool burns the
comp, the user only pays what they actually borrowed.
- Each dialog resets the pipeline on open and fingerprints legs;
changing inputs after a partial run can't resume against stale
specs.
- Implement repayMUSD and closeTrove on both the sim and execution
sides (were previously v2-stubs).
Timidan added a commit that referenced this pull request May 28, 2026
Applied 9 unambiguous fixes from a 10-zone CLAUDE.md audit (~150 total
findings). Only items with zero behavior change, zero parallel-work
conflict (PR #20 lifi-intents, #21 mezo, #22 cleanup), and clear
dead-code or surface-confusion signal were applied; the rest are
deferred to the PR description as a backlog.
Net: 12 files, -65 lines net.
Surface confusion (P1):
- structStorageDecoding.ts:484 — collapse identical-branches ternary
'const elementSize = elementType === 'address' ? 1 : 1' → '= 1'
- storageSlotCalculator.ts:86 — parseSlotInput dropped redundant hex
branch (both branches called BigInt(trimmed))
- edbTraceConverter.ts:55 — same redundant-hex-branch in
parseTraceValue
Speculative API surface (P2):
- SolidityViewer.tsx — removed unused props highlightLine,
scrollToLine, theme (sole caller never passes any)
- PackingVisualizer.tsx — removed unused rawHex prop + caller's pass
- api/{lifi-composer,lifi-earn,edb-proxy}.ts — dropped 'HEAD' from
ALLOWED_METHODS (no caller issues HEAD)
Dead exports (P3):
- scripts/bridge-security.mjs — sanitizeForLogging (zero callers)
- scripts/bridge-config.mjs — TRACE_DETAIL_COMPACT_ARTIFACTS env
constant (zero readers)
- eslint.config.js — ignore globs for nonexistent dirs
(current_bundle, test-results, test-*, **/test-*.js, test-app-*)
Sign up for freeto 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.

2 participants

@Timidan