feat: Mezo Lens integration (Stack / Borrow / Save / Lock / Swap / Liquidity) + chain-aware EDB bridge#21
Conversation
…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.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
💡 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".
| ].filter((event, index, allEvents) => { | ||
| const key = eventKey(event, index); | ||
| return allEvents.findIndex((candidate, candidateIndex) => | ||
| eventKey(candidate, candidateIndex) === key | ||
| ) === index; |
There was a problem hiding this comment.
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 👍 / 👎.
There was a problem hiding this comment.
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
| File | Description |
|---|---|
| vercel.json | Adds Mezo Blockscout proxy routes and LI.FI intents API routing on Vercel. |
| src/utils/transaction-simulation/responseParsing.ts | Improves source provider detection for contract artifacts (explicit provider fields + meta fallbacks). |
| src/utils/transaction-simulation/bridgeSimulation.ts | Preserves sourceProvider when inlining artifacts from bridge responses. |
| src/utils/transaction-simulation/artifactFetching.ts | Adds Mezo chainIds to Blockscout instance mapping. |
| src/utils/tokenMovements.ts | Seeds token metadata for Mezo assets (MEZO/BTC/MUSD/sMUSD). |
| src/utils/simulationArtifacts.ts | Makes EDB trace conversion chain-aware for native asset name/symbol. |
| src/utils/resolver/sources/blockscout.ts | Makes Blockscout URL construction robust across /api, /api/v2, and proxy bases; adds Mezo proxy mapping. |
| src/utils/edbTraceConverter.ts | Adds native asset overrides, event dedupe keyed by call-frame + emission index, and collapses native movements to net deltas per address. |
| src/services/SimulationHistoryService.ts | Bumps IndexedDB version to v3, hardens upgrade/index creation, and improves filtering null-safety. |
| src/services/DebugBridgeService.ts | Updates debug bridge behavior to support new chain-aware routing/simulation behavior. |
| src/lib/intents/standardOrder.ts | Adds intent order modeling utilities for LI.FI intents. |
| src/lib/intents/nonce.ts | Adds nonce helpers for intent signing/validation. |
| src/lib/intents/eip7930.ts | Adds EIP-7930 related helpers for intent formats. |
| src/lib/intents/deadlines.ts | Adds deadline utilities for intent payloads. |
| src/lib/intents/contracts.ts | Adds contract-related helpers for intents. |
| src/lib/intents/addressBytes.ts | Adds address/bytes encoding helpers for intents. |
| src/hooks/useUniversalSearch.ts | Extends search to include Mezo-related navigation/content updates. |
| src/contexts/debug/useDebugPrep.ts | Updates debug preparation flow to support new simulation/routing behavior. |
| src/components/SimulationHistoryPage.tsx | Updates simulation history UI to reflect IDB schema changes and new fields. |
| src/components/simulation-results/useSimulationPageState.ts | Updates simulation page state management for new artifacts/trace behavior. |
| src/components/simulation-results/SummaryTab.tsx | Updates summary rendering for revised asset movement/native symbol behavior. |
| src/components/simulation-results/EventsTab.tsx | Updates events table behavior consistent with improved dedupe/topics handling. |
| src/components/simulation-results/eventDecoder.ts | Updates event decoding pipeline to align with new trace/artifact fields. |
| src/components/simulation-results/ContractsTab.tsx | Updates contract verification/source-provider badges (Blockscout vs Sourcify vs Etherscan). |
| src/components/shared/RouteMetaTags.tsx | Adds/updates OG/meta tags for Mezo integration pages. |
| src/components/Navigation.tsx | Adds Mezo navigation entries and related routing. |
| src/components/MobileDrawer.tsx | Ensures Mezo navigation works in mobile drawer. |
| src/components/integrations/mezo/tabs/SaveTab.tsx | Adds Mezo Lens “Save” tab UI and simulation wiring. |
| src/components/integrations/mezo/TabBar.tsx | Adds Mezo Lens tab navigation component. |
| src/components/integrations/mezo/sim/views.ts | Adds read-only view calls used in Mezo bundle simulations. |
| src/components/integrations/mezo/sim/types.ts | Adds shared types for Mezo simulation legs/views/results. |
| src/components/integrations/mezo/sim/ethSimulateV1.ts | Implements atomic bundle simulation builder for Mezo flows. |
| src/components/integrations/mezo/sim/bundles/swap.ts | Adds swap bundle legs/views for Mezo Lens. |
| src/components/integrations/mezo/sim/bundles/stack.ts | Adds stack bundle legs/views for Mezo Lens. |
| src/components/integrations/mezo/sim/bundles/save.ts | Adds save bundle legs/views for Mezo Lens. |
| src/components/integrations/mezo/sim/bundles/lock.ts | Adds lock bundle legs/views for Mezo Lens. |
| src/components/integrations/mezo/sim/bundles/liquidity.ts | Adds liquidity bundle legs/views for Mezo Lens. |
| src/components/integrations/mezo/sim/bundles/borrow.ts | Adds borrow bundle legs/views for Mezo Lens. |
| src/components/integrations/mezo/sim/buildCalls.ts | Adds shared call construction helpers for Mezo bundles. |
| src/components/integrations/mezo/preview/PreviewPanel.tsx | Adds Mezo plan preview panel for all bundle legs. |
| src/components/integrations/mezo/preview/DecodedLegList.tsx | Adds decoded leg rendering for preview UX. |
| src/components/integrations/mezo/PositionsSidebar.tsx | Adds positions sidebar for Mezo Lens layouts. |
| src/components/integrations/mezo/pipeline/useMezoLegPipeline.ts | Adds leg pipeline orchestration for Mezo plan building/simulation. |
| src/components/integrations/mezo/pipeline/MezoLegTimeline.tsx | Adds timeline UI for leg execution/simulation steps. |
| src/components/integrations/mezo/pipeline/mezoLegs.ts | Defines Mezo leg models and composition rules. |
| src/components/integrations/mezo/pipeline/legHandlers.ts | Implements per-leg decoding/formatting/handling logic. |
| src/components/integrations/mezo/MezoLensPage.tsx | Adds Mezo Lens top-level page routing + tab layout. |
| src/components/integrations/mezo/index.ts | Exposes Mezo integration entrypoint(s). |
| src/components/integrations/mezo/hooks/useReserves.ts | Adds Mezo pool reserve querying hook(s). |
| src/components/integrations/mezo/hooks/usePriceFeed.ts | Adds Mezo price feed querying hook(s). |
| src/components/integrations/mezo/hooks/useFindPool.ts | Adds Mezo pool discovery hook(s). |
| src/components/integrations/mezo/HonestyFooter.tsx | Adds Mezo Lens disclosure/footer component. |
| src/components/integrations/mezo/glossary.ts | Adds Mezo glossary terms for UI help text. |
| src/components/integrations/mezo/copy.ts | Adds Mezo-specific copy strings. |
| src/components/integrations/mezo/constants.ts | Adds Mezo chain constants/addresses for simulations. |
| src/components/integrations/mezo/components/WorkbenchBody.tsx | Adds shared layout for Mezo Lens workbench. |
| src/components/integrations/mezo/components/Term.tsx | Adds term/help UI component(s) for Mezo Lens. |
| src/components/integrations/mezo/components/SectionEyebrow.tsx | Adds section heading UI component(s). |
| src/components/integrations/mezo/components/MezoTopBar.tsx | Adds Mezo Lens top bar UI. |
| src/components/integrations/mezo/components/FlowRibbon.tsx | Adds flow/status ribbon UI for Mezo Lens. |
| src/components/integrations/mezo/components/AssetInput.tsx | Adds Mezo-specific asset input component(s). |
| src/components/integrations/mezo/ChainGate.tsx | Gates Mezo Lens UX by selected chain. |
| src/components/integrations/lifi-earn/VaultList.tsx | Updates LI.FI Earn UI to support intents-driven behaviors. |
| src/components/integrations/lifi-earn/useIntentOrderStatus.ts | Adds hook for tracking intent order status. |
| src/components/integrations/lifi-earn/types.ts | Tightens types related to LI.FI Earn / intents. |
| src/components/integrations/lifi-earn/txUtils.ts | Updates tx utils for intent-based flows. |
| src/components/integrations/lifi-earn/TokenIcon.tsx | Updates token icon handling for Earn/intents flows. |
| src/components/integrations/lifi-earn/intentsApi.ts | Adds client API wrapper for intents endpoint. |
| src/components/integrations/lifi-earn/hooks/useWithdrawQuote.ts | Updates withdraw quoting to support intents semantics. |
| src/components/integrations/lifi-earn/earnApi.ts | Updates Earn API client behavior/types. |
| src/components/integrations/lifi-earn/destinationTokenOptions.ts | Adds destination token option logic for Earn flows. |
| src/components/integrations/lifi-earn/concierge/VaultRecommendations.tsx | Updates concierge recommendations for intents support. |
| src/components/integrations/lifi-earn/concierge/types.ts | Updates concierge types to reflect new intent structures. |
| src/components/integrations/lifi-earn/concierge/LlmErrorAlert.tsx | Updates LLM error UX for concierge flows. |
| src/components/integrations/lifi-earn/concierge/intent/intentLegs.ts | Adds intent-based leg generation / degradation logic. |
| src/components/integrations/lifi-earn/concierge/intent/hooks/useVaultsByIntent.ts | Updates vault fetching to support intents. |
| src/components/integrations/lifi-earn/concierge/intent/hooks/useIntentRecommendation.ts | Updates intent recommendation logic. |
| src/components/integrations/lifi-earn/concierge/IdleSweepPanel.tsx | Updates Idle Sweep UI for updated flows. |
| src/components/integrations/lifi-earn/concierge/FlowDiagram.tsx | Updates concierge flow diagram for new leg types. |
| src/components/integrations/lifi-earn/concierge/fallback.ts | Updates concierge fallback behavior with intents integration. |
| src/components/integrations/IntegrationsHub.tsx | Adds Mezo integration entry to the integrations hub. |
| src/components/ExecutionStackTrace.tsx | Updates execution stack trace UI consistent with new simulation artifacts. |
| src/chains/registry.ts | Registers Mezo chain metadata (native currency symbol/name) and related chain config. |
| scripts/trace-processing.mjs | Updates trace processing script for new trace/artifact behaviors. |
| scripts/simulator-bridge.mjs | Updates simulator bridge script to support chain-aware routing. |
| scripts/artifact-compactor.mjs | Updates artifact compaction script for new artifact shapes/source providers. |
| README.md | Documents new env vars, Mezo integration, and updated simulation/bridge behavior. |
| public/logos/mezo.svg | Adds Mezo logo asset. |
| public/logos/mezo-wordmark.svg | Adds Mezo wordmark asset. |
| index.html | Updates metadata/links for Mezo and updated routing. |
| data/mezoContracts.ts | Adds Mezo contract registry/constants used by the Lens. |
| api/lifi-intents.ts | Adds serverless API proxy for LI.FI intents (including rate limiting). |
| api/edbShared.ts | Adds shared chainId extraction and bridge URL resolution helpers. |
| api/edb-proxy.ts | Implements chain-aware EDB bridge routing and streaming/non-streaming behaviors. |
| .gitignore | Updates ignores for new artifacts/assets. |
| .env.example | Documents new env vars (EDB_DEFAULT_BRIDGE_URL, EDB_MEZO_BRIDGE_URL, etc.). |
| .codegraph/.gitignore | Adds ignore rules for codegraph outputs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 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); | ||
| } |
| 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 }, | ||
| ); |
| // 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.
There was a problem hiding this comment.
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.onblockedimmediately rejectsinitPromise, but the open request may later unblock and still fireonsuccess, settingthis.dbafter 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 lateronsuccess, or (preferably) surface a blocked state to the UI while keeping the init promise pending until the upgrade either succeeds or errors.
| 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; | ||
| }); |
| if (isSSE) { | ||
| // Abort upstream when client disconnects | ||
| req.on("close", () => controller.abort()); | ||
| } else { | ||
| // Regular requests get a hard timeout |
| 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.
| 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, |
| 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; | ||
| }); |
| const parsedQueryChainId = queryChainId ? Number(queryChainId) : null; | ||
| const chainId = Number.isInteger(parsedQueryChainId) | ||
| ? parsedQueryChainId | ||
| : extractChainIdFromRawJsonBody(rawBody, req.headers["content-type"]); |
| 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.
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.
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).
Summary
eth_simulateV1bundles so the user sees the resulting trove, ICR, LP tokens, swap quote, etc. before any wallet write.chainIdper 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.What ships in each commit
e27f0e7chain config (registry, contracts, CSP, env docs)1b2148achain-aware bridge routing (api/edbShared.ts, vite proxy, Vercel proxy)632f87cMezo Lens app (46 files, all undersrc/components/integrations/mezo/)1bb6c4etrace + Blockscout badge + token movement net-per-addressd5407ddSimulationHistory IDB v2 → v3 migration05a7981LI.FI Earn drive-by type tighteningdac6ec8nav, search, og tags, logos, public mezo-labd685a4aedb submodule pointer bumpTest plan
feat/mezo;/integrations/mezoloads, wallet switch targets chain 316110x75b67f493f482ac707309bd55c0e4979e3fc1ca69d13be6b1889b27846f7351f: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-extended—feat/mezobranch — Mezo chain_metadata + stateful precompile inspector + source-provider tagging