All notable changes to Meridian will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- MeridianVault: per-user deposit entry time. The contract now stamps
env.ledger().timestamp()on a user's first deposit (top-ups keep the original; a full withdrawal clears it) and exposes it viaget_entry_time. The/api/v1/positionsendpoint (and the local Fastify route) now return the realentryTimeinstead of the previous hardcoded0. Covered bydeposit_records_entry_time,topup_keeps_original_entry_time,full_withdraw_clears_entry_time, andentry_time_defaults_to_zero.
- MeridianVault: add admin safety rails. New
set_paused/is_pausedemergency switch halts deposits during an incident, while withdrawals stay open so a pause can never trap user funds. Addedset_admin/get_adminfor admin key rotation without redeploying. Covered bypaused_blocks_deposit,withdraw_works_while_paused,unpause_re_enables_deposits, andset_admin_rotates_admin. - MeridianVault: fix first-depositor share inflation attack. Share price is now
computed against a virtual shares/assets offset (OpenZeppelin ERC-4626 mitigation)
instead of the raw on-chain USDC balance, so an attacker can no longer donate USDC
directly to the contract to skim later depositors via rounding. Added the
inflation_attack_is_unprofitableregression test.
- Unit-test the deposit money-math. Exported and covered
toStroops(decimal USDC → 7-decimal stroops, incl. sub-unit precision and truncation behaviour) instellar-sdk-helpers, previously untested code on the path that determines on-chain deposit amounts.
/api/v1/vaults: cache at the CDN edge. AddedCache-Control: s-maxage=60, stale-while-revalidate=300so the aggregated vault list is served from Vercel's edge — cutting DeFiLlama call volume and letting the edge keep serving the last good payload through a transient DeFiLlama outage instead of failing the dashboard.
- Re-enabled the Soroban contract job (
cargo test+ wasm release build) now thatpackages/contractshas aCargo.toml. - Typecheck the Vercel serverless functions in
api/(newpnpm typecheck:api). They live outside the pnpm workspace and were previously never typechecked in CI.
- Freighter wallet adapter integration
- Live Blend Capital pool APY and TVL data
- Live DeFindex vault APY and TVL data
- APY aggregation API endpoint with Redis caching
- Unsigned Soroban deposit/withdraw transaction XDR builder
- Soroban router contract for atomic single-transaction rebalancing
- Yield history sparkline chart per vault
- French/English i18n with
react-i18nextand locale detection
0.1.0 - 2026-05-09
pnpm+ Turborepo monorepo withapps/web,apps/api,packages/shared,packages/stellar-sdk-helpers,packages/contractspnpm-workspace.yamlfor correct pnpm workspace resolution- Root
tsconfig.jsonextended by all packages - GitHub Actions CI workflow: lint, typecheck, and test across all packages
- ESLint with
@typescript-eslintstrict rules for web and API - Dependabot configuration for npm and GitHub Actions dependencies
CONTRIBUTING.mdwith branch naming, commit convention, and PR processPULL_REQUEST_TEMPLATE.mdwith type-of-change checklist and protocol context fields
- Vite + React 18 frontend (migrated from Next.js 14)
- Tailwind CSS with PostCSS — dark theme palette
WalletConnectcomponent (placeholder, Freighter integration pending)VaultCardcomponent — displays APY, TVL, asset, and protocol badgeVaultList— renders 4 mock vaults (USDC/EURC across Blend and DeFindex)PortfolioSummary— total deposited, total earned, and per-position breakdown with mock data- Zustand wallet store (
useWalletStore) apps/web/src/lib/api.ts— typedapiFetchwrapper usingVITE_API_URL
- Fastify 4 API skeleton with CORS and rate-limiting plugins
GET /api/v1/vaults— stub returning empty vault listGET /api/v1/vaults/:id— stub returning 404POST /api/v1/tx/deposit— validates body with Zod; returns 501 pending implementationPOST /api/v1/tx/withdraw— validates body with Zod; returns 501 pending implementationGET /health— liveness endpoint
getBlendPoolInfo(config)— stub; decodes Blend pool APY + TVL (implementation pending)buildBlendDepositTx(config, depositor, amount)— stub; builds unsigned Soroban XDR (pending)getDefindexVaultInfo(config)— stub; decodes DeFindex vault APY + TVL (pending)buildDefindexDepositTx(config, depositor, amount)— stub; builds unsigned Soroban XDR (pending)buildHorizonServer(config)— returns a configuredHorizon.ServergetAccountBalances(server, publicKey)— fetches all balances for a Stellar account
DepositRequestSchemaandWithdrawRequestSchema— Zod schemas shared by API and frontendSUPPORTED_STABLECOINS,PROTOCOL_IDS,CONTRACT_ADDRESSES,STELLAR_NETWORKSconstantsformatUsdAmount(stroops)— formats a bigint stroops value to a USD stringparseUsdAmount(display)— parses a USD display string to bigint stroopsfromStroops(stroops)— converts stroops bigint to a JavaScript numbershortenAddress(address)— truncates a Stellar G-address for display
- Package scaffold for Soroban Rust contracts (no Cargo.toml yet — pending)
scripts/deploy-testnet.sh— placeholder deploy script for testnet
- N/A — initial release
- N/A — initial release