Build on MUSD
without rebuilding
the hard parts.
The typed, fork-verified TypeScript SDK for MUSD, Mezo's Bitcoin-backed stablecoin. The Trove lifecycle, the math, and the hint dance, handled.
npm i @musd-kit/core @musd-kit/react - Borrowing fee
- ·
- Total debt
- ·
- Collateral ratio
- ·
- Liquidation price
- ·
- Meets minimum
- ·
await musd.previewOpen({ collateral: parseBtc('0.05'), debt: parseMusd('2500') }) Read-only via the shipped @musd-kit/core. No wallet, no transaction.
ARCHITECTURE
How musd-kit works
From your first line of code to a managed Trove: the whole flow, abstracted. Trace a call through the layers.
Reads come straight from the contract getters: contract-authoritative. The Hint and Math engine stays out of the path.
Your dApp
No provider of its own. The hooks read the wagmi context Passport (or any wagmi setup) already established. A few lines to a live position.
// uses your existing wagmi + Passport context
const { data: trove } = useTrove({ address }) React hooks
Wagmi-idiomatic hooks with block-watching refetch and typed errors. Selectors over one shared query, so health factor and liquidation price share a single fetch. useBorrowingPower returns the contract ceiling, a limit and not an amount (MK-100); useDrawForMargin sizes a draw for a horizon and a price fall the user chooses (MK-240).
const { openTrove, isPending, error } = useOpenTrove()
// A draw for the margin the user chose (MK-240)
const { data } = useDrawForMargin({ collateral, horizonSeconds, priceFallBps }) musd-kit core
The framework-agnostic engine (viem). Live reads come straight from the contract getters; previews are the only client-side math. The same core powers a React dApp or a headless Node keeper.
const musd = createMusdClient({ chainId, publicClient })
const trove = await musd.getTrove(address) Hint + Math engine
The correctness-critical layer: insertion hints computed for every write, ICR, liquidation price, borrowing power, and interest projection, validated against a fork, the contracts’ own pure helpers, and actual transaction outcomes; coverage is stated per surface in the validated surface table.
const icr = computeICR({ collateral, entireDebt, price })
const liq = computeLiquidationPrice({ collateral, entireDebt }) Mezo contracts
The protocol. Reads are contract-authoritative; every write simulates before it sends. Bundled, verified addresses with the official as-const ABIs.
import { troveManagerAbi, sortedTrovesAbi } from '@musd-kit/core'
// reads are contract-authoritative; writes simulate before they send CAPABILITIES
Everything you need to build on MUSD.
The full Trove lifecycle, hints absorbed
Open, add or withdraw collateral, borrow, repay, adjust, refinance, close. Every write computes the insertion hints, the borrowing fee and the gas reserve, then simulates before it sends.
- insertion hints
- borrowing fee
- gas reserve
- simulate
await musd.openTrove({ collateral, debt })
await musd.addCollateral({ amount })
await musd.repay({ amount })
await musd.close() Contract-authoritative reads
The full live position from the protocol’s own getters. Correct by construction, interest to the second.
const t = await musd.getTrove(address) Preview and borrowing power
Show users exactly what they’ll get before they sign, validated against the chain to the wei.
await musd.previewOpen({ collateral, debt }) Redemption and a liquidation keeper
Redeem MUSD for BTC, with fee and truncation surfaced, never silent. Run a permissionless keeper with mode-aware checks.
await musd.redeem({ amount })
if (await musd.isLiquidatable(b)) await musd.liquidate(b) Wagmi-idiomatic React hooks
Block-watching refetch and typed errors. No provider of its own; it consumes the wagmi context Passport already gives you.
const { data: trove } = useTrove({ address })
const { openTrove, error } = useOpenTrove() Typed errors, zero hardcoding
A discriminated MusdError taxonomy mapped from real reverts. Every governable value is read on-chain, never hardcoded.
catch (e) {
if (e instanceof BelowMinimumDebt)
showMin(e.context.minNetDebt)
} WHY TRUST IT
Correctness is the product.
Most SDKs ask you to trust them. musd-kit was built against a fork of real Mezo and verified on testnet, so the proof is checkable, not promised.
WHAT YOU DON'T HAVE TO BUILD
The fiddly hard parts, handled for you.
- Insertion hints for the sorted Trove list, recomputed on every write
- The borrowing fee plus the 200 MUSD gas reserve, in the debt math
- Simulate-before-send on every transaction, with a measured gas margin on top
- Discriminated typed errors, mapped from the real contract reverts
- Governable values (minNetDebt, fees, rates, price) read live, never hardcoded
Get these wrong near the liquidation threshold and it costs a user collateral.
-
Verified against real Mezo contracts
A fork of real Mezo backs the whole suite, and a differential harness checks each preview verdict against what the chain actually does. A live testnet lifecycle is a manual gate before publishing. Not mocks.
-
Proven live on Mezo testnet
A real read returns the live BTC/USD price and the system TCR through the shipped package. The calculator above runs it.
-
A headless keeper runs end to end, on a fork
Core-only, no React. On a fork of real Mezo it opens a position, drops the oracle under MCR, scans the sorted list and collects the 200 MUSD gas compensation the protocol pays per liquidation. Not reproducible on live testnet, which has no oracle you can move.
See the verification ledger and ground-truth in the docs.
INTEROP
Works with your stack.
Framework-agnostic core · wagmi-idiomatic React hooks · runs in Node or the browser.
- Built on
- viem
- wagmi
- Connects wallets via
- Passport
- For MUSD on
- Mezo
- Runs on
- Node
- the browser
- React hooks
- React
QUICKSTART
Start in minutes.
From an empty file to a live read against Mezo testnet, in three steps.
-
Install
Add the core. The React hooks are a separate, optional package.
npm i @musd-kit/core # add @musd-kit/react for the hookspnpm add @musd-kit/core # add @musd-kit/react for the hooksyarn add @musd-kit/core # add @musd-kit/react for the hooksbun add @musd-kit/core # add @musd-kit/react for the hooks -
Create a client
Pass a viem public client. That is all the core needs to read.
import { createMusdClient } from '@musd-kit/core' const musd = createMusdClient({ chainId: 31611, publicClient })Drop in the hooks
No provider of its own. The hooks consume the wagmi context Passport already gives you.
import { useTrove } from '@musd-kit/react' // inside your wagmi + Passport app, no provider of its own const { data: trove } = useTrove({ address }) -
Your first call
Read live state. This is the same read the calculator in the hero runs.
const price = await musd.getOraclePrice() const trove = await musd.getTrove(address)RETURNS- price
- the live BTC/USD from Mezo's native oracle
- trove
- { collateral, entireDebt, icr, liquidationPrice, healthFactor }
Your first call
Read and write from a component, with typed errors.
const { openTrove, isPending, error } = useOpenTrove()RETURNS- trove
- the live position, refetched on each block
- error
- a typed MusdError you can branch on, like BelowMinimumDebt
Building a liquidation keeper? See the keeper example →
LIVE DEMO
Try it live.
Drag the sliders or pick a preset: the fee, total debt, collateral ratio and the price BTC can fall before liquidation all recompute from the real Mezo testnet oracle, through the shipped package.
FAQ
Questions, answered.
The honest answers: what musd-kit is, what it is not, and how the correctness is checked.
Still have questions? Start a discussion on GitHub →
No. It is open-source, community-built tooling, not affiliated with or endorsed by Mezo or Thesis. It talks to Mezo’s public contracts.
Not yet. It is pre-1.0, intended for testnet and evaluation, and the API may change before a stable 1.0. It is single-author and has not been audited. What it does have: a harness against a fork of the real Mezo contracts on every push, a differential sweep that checks each preview verdict against what the chain actually does, and a full lifecycle run against live testnet before every publish.
Mezo testnet (chainId 31611) and mainnet (31612). The client reads the governable parameters live per network. See the ground-truth reference.
No. The React hooks consume any wagmi context, and Passport is the easiest way to get one. The core needs only a viem client, so musd-kit complements Passport rather than replacing it.
Yes, MIT licensed. View, fork, and contribute on GitHub.
Every release runs against a fork of real Mezo: a differential harness sweeps generated cases through each preview and then attempts the operation on-chain, comparing the verdict to what actually happened. A live testnet lifecycle is a separate manual gate run before publishing. No governable value is hardcoded. The sweep covers eight operations, every write that has a preview to compare, and not redemption, liquidation or claim, which have none; what is and is not covered is stated per surface in the validated surface table.