The Metastable SDK is a TypeScript library for interacting with the Metastable protocol on the Sui blockchain. The Metastable protocol allows users to mint and burn meta coins (e.g., mUSD, mSUI) by depositing or withdrawing supported assets into/from Meta Vaults, with dynamic withdrawal fees to maintain target liquidity distributions.
- Deposit: Mint meta coins (e.g., mUSD) by depositing supported assets (e.g., USDC) into a Meta Vault. Deposits are free (0% fee) and use on-chain price feeds for accurate conversions.
- Withdraw: Burn meta coins to withdraw assets from a Meta Vault, subject to a dynamic withdrawal fee (0.01% to 1%) that incentivizes target liquidity distributions.
- Fetch Vault Data: Retrieve vault information, such as deposit caps, total deposits, and fees for each supported asset.
- Calculate Fees and Limits: Compute dynamic withdrawal fees, maximum deposits, and maximum withdrawals based on vault data and asset prices.
Install the SDK using npm:
npm install metastable-ts-sdk
Ensure you have the following dependencies installed in your project:
- @mysten/sui (for Sui blockchain interactions)
- @pythnetwork/pyth-sui-js (for Pyth price feeds)
First, create an instance of MetastableSDK with a SuiClient connected to the Sui blockchain.
import { SuiClient } from "@mysten/sui/client";
import { MetastableSDK } from "metastable-ts-sdk";
const suiClient = new SuiClient({ url: "https://fullnode.mainnet.sui.io" });
const sdk = new MetastableSDK({ suiClient });
Deposit a supported asset into a Meta Vault to mint meta coins. Deposits are free (0% fee). The amount of meta coin minted is determined by the on-chain price feed.
import { M_USD } from "metastable-ts-sdk";
async function mintMUSD() {
try {
const tx = await sdk.buildMintTx({
mCoin: M_USD.coin,
coin: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC",
amountIn: 100,
walletAddress: "0xYourWalletAddress",
minAmountOut: 99.5, // Optional, defaults to 0
});
// Sign and execute the transaction using your wallet
// Example: const result = await wallet.signAndExecuteTransaction({ transaction: tx });
console.log("Mint transaction built:", tx);
} catch (error) {
console.error("Error minting mUSD:", error);
}
}
mintMUSD();
Burn meta coins to withdraw assets from a Meta Vault. Withdrawals incur a dynamic fee (0.01% to 1%) based on the vault's target liquidity distribution.
import { M_USD } from "metastable-ts-sdk";
async function burnMUSD() {
try {
const tx = await sdk.buildBurnTx({
mCoin: M_USD.coin,
coin: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC",
amountIn: 50,
walletAddress: "0xYourWalletAddress",
minAmountOut: 49.5, // Optional, defaults to 0
});
// Sign and execute the transaction using your wallet
// Example: const result = await wallet.signAndExecuteTransaction({ transaction: tx });
console.log("Burn transaction built:", tx);
} catch (error) {
console.error("Error burning mUSD:", error);
}
}
burnMUSD();
Retrieve data about a Meta Vault, including deposit caps, total deposits, fees, and priorities for each supported asset.
import { M_USD } from "metastable-ts-sdk";
async function fetchVaultData() {
try {
const vault = await sdk.fetchVault({ mCoin: M_USD.coin });
console.log("mUSD Vault Data:", vault);
// Example output:
// {
// mCoin: '0x...::musd::MUSD',
// coins: {
// '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC': {
// depositCap: 1000000000000n,
// totalDeposits: 500000000000n,
// minFee: 10000000000000000n, // 0.01%
// maxFee: 500000000000000000n, // 0.5%
// priority: 500n,
// decimals: 6
// },
// ...
// },
// supply: 1000000000000n,
// totalPriorities: 1000n,
// metaCoinDecimals: 9
// }
} catch (error) {
console.error("Error fetching vault data:", error);
}
}
fetchVaultData();
Calculate the dynamic withdrawal fee for burning meta coins. The fee is based on the vault's target liquidity distribution, as defined by:
- Target Liquidity = (Total Deposits × Asset Priority) / Total Priorities
- End Liquidity = Current Liquidity - Withdrawal Amount
-
Dynamic Fee:
- If End Liquidity ≥ Target Liquidity: Min Fee (0.01%)
- If End Liquidity < Target Liquidity: Max Fee - ((Max Fee - Min Fee) / Target Liquidity × End Liquidity)
import { M_USD } from "metastable-ts-sdk";
async function calculateWithdrawalFee() {
try {
const vault = await sdk.fetchVault({ mCoin: M_USD.coin });
const usdcCoin =
"0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC";
const amountToBurn = 50; // Amount of mUSD to burn
const usdcPrice = 1; // Price of USDC in USD
const mUSDPrice = 1; // Price of mUSD in USD
const fee = sdk.calcBurnFeeFromAmountIn({
vault,
coin: usdcCoin,
amountIn: amountToBurn,
coinPrice: usdcPrice,
mCoinPrice: mUSDPrice,
});
console.log(`Dynamic Withdrawal Fee: ${(fee * 100).toFixed(2)}%`);
} catch (error) {
console.error("Error calculating withdrawal fee:", error);
}
}
calculateWithdrawalFee();
Determine the maximum amount of an asset you can deposit into a Meta Vault, based on the vault's deposit cap and current total deposits.
import { M_USD } from "metastable-ts-sdk";
async function calculateMaxDeposit() {
try {
const vault = await sdk.fetchVault({ mCoin: M_USD.coin });
const usdcCoin =
"0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC";
const maxDeposit = sdk.calcMaxDeposit({ vault, coin: usdcCoin });
console.log(`Maximum USDC Deposit: ${maxDeposit} USDC`);
} catch (error) {
console.error("Error calculating max deposit:", error);
}
}
calculateMaxDeposit();
Determine the maximum amount of an asset you can withdraw from a Meta Vault, accounting for the dynamic withdrawal fee.
import { M_USD } from "metastable-ts-sdk";
async function calculateMaxWithdrawal() {
try {
const vault = await sdk.fetchVault({ mCoin: M_USD.coin });
const usdcCoin =
"0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC";
const usdcPrice = await sdk.fetchCoinPrice({ coin: usdcCoin }); // Price of USDC in USD
const mUSDPrice = await sdk.fetchCoinPrice({ coin: vault.mCoin }); // Price of mUSD in USD
const maxWithdraw = sdk.calcMaxWithdraw({
vault,
coin: usdcCoin,
coinPrice: usdcPrice,
mCoinPrice: mUSDPrice,
});
console.log(`Maximum USDC Withdrawal: ${maxWithdraw} USDC`);
} catch (error) {
console.error("Error calculating max withdrawal:", error);
}
}
calculateMaxWithdrawal();
The SDK provides functions to calculate the amounts involved in minting and burning meta coins.
- Calculate Mint Amount Out from Amount In: Determine how much meta coin you will receive for a given amount of collateral coin deposited.
const amountOut = sdk.calcMintAmountOutFromAmountIn({
amountIn: 100, // Amount of USDC to deposit
coinPrice: await sdk.fetchCoinPrice({ coin: usdcCoin }), // Price of USDC in USD
mCoinPrice: await sdk.fetchCoinPrice({ coin: vault.mCoin }), // Price of mUSD in USD
});
console.log(`Minted mUSD: ${amountOut}`); // e.g., "Minted mUSD: 100"
- Calculate Mint Amount In from Amount Out: Determine how much collateral coin is needed to mint a specific amount of meta coin.
const amountIn = sdk.calcMintAmountInFromAmountOut({
amountOut: 100, // Desired amount of mUSD to mint
coinPrice: await sdk.fetchCoinPrice({ coin: usdcCoin }), // Price of USDC in USD
mCoinPrice: await sdk.fetchCoinPrice({ coin: vault.mCoin }), // Price of mUSD in USD
});
console.log(`Required USDC: ${amountIn}`); // e.g., "Required USDC: 100"
- Calculate Burn Amount Out from Amount In: Determine how much collateral coin you will receive for burning a specific amount of meta coin, accounting for the dynamic fee.
try {
const amountOut = sdk.calcBurnAmountOutFromAmountIn({
vault,
coin: usdcCoin,
amountIn: 50, // Amount of mUSD to burn
coinPrice: await sdk.fetchCoinPrice({ coin: usdcCoin }),
mCoinPrice: await sdk.fetchCoinPrice({ coin: vault.mCoin }),
});
console.log(`Received USDC: ${amountOut}`); // e.g., "Received USDC: 49.5"
} catch (error) {
console.error("Error calculating burn amount out:", error);
}
- Calculate Burn Amount In from Amount Out: Determine how much meta coin you need to burn to receive a specific amount of collateral coin, accounting for the dynamic fee.
try {
const amountIn = sdk.calcBurnAmountInFromAmountOut({
vault,
coin: usdcCoin,
amountOut: 50, // Desired amount of USDC to receive
coinPrice: await sdk.fetchCoinPrice({ coin: usdcCoin }),
mCoinPrice: await sdk.fetchCoinPrice({ coin: vault.mCoin }),
});
console.log(`Required mUSD: ${amountIn}`); // e.g., "Required mUSD: 50.5"
} catch (error) {
console.error("Error calculating burn amount in:", error);
}
The Metastable SDK provides a method called fetchCoinPrice
to retrieve the latest price for a specified coin type. This functionality is essential for tasks like calculating conversions, fees, or any other price-dependent values. The method supports:
-
Pyth-supported coins (e.g., SUI, USDC): Prices are fetched directly from Pyth price feeds.
-
mSUI and Liquid Staking Tokens (LSTs): Prices are calculated based on exchange rates relative to SUI, using on-chain data.
Here’s how to fetch the price of SUI, a coin supported by Pyth price feeds:
import { SUI } from "metastable-ts-sdk";
async function fetchSUIPrice() {
try {
const price = await sdk.fetchCoinPrice({ coin: SUI.coin });
console.log(`SUI Price: ${price} USD`); // Example output: "SUI Price: 1.5 USD"
} catch (error) {
console.error("Error fetching SUI price:", error);
}
}
fetchSUIPrice();
For mSUI, the price is calculated using its exchange rate relative to SUI:
import { M_SUI } from "metastable-ts-sdk";
async function fetchMSUIPrice() {
try {
const price = await sdk.fetchCoinPrice({ coin: M_SUI.coin });
console.log(`mSUI Price: ${price} USD`); // Example output: "mSUI Price: 1.5 USD"
} catch (error) {
console.error("Error fetching mSUI price:", error);
}
}
fetchMSUIPrice();
For Liquid Staking Tokens like AF_SUI, the price is similarly derived from exchange rates relative to SUI:
import { AF_SUI } from "metastable-ts-sdk";
async function fetchLSTPrice() {
try {
const price = await sdk.fetchCoinPrice({ coin: AF_SUI.coin });
console.log(`AF_SUI Price: ${price} USD`); // Example output: "AF_SUI Price: 1.5 USD"
} catch (error) {
console.error("Error fetching AF_SUI price:", error);
}
}
fetchLSTPrice();
-
Deposit Caps: Each Meta Vault enforces deposit caps for supported assets. Check the latest caps on X (@MetaStables) or use
fetchVault
to retrieve them programmatically. -
Dynamic Fees: Withdrawal fees range from 0.01% to 1%, depending on the vault's liquidity distribution. Use
calcBurnFeeFromAmountIn
to estimate fees before withdrawing. -
Price Feeds: The SDK uses Pyth price feeds for accurate conversions between meta coins and collateral assets. Ensure your
SuiClient
is connected to a Sui network with access to these feeds. - Error Handling: Always wrap SDK calls in try-catch blocks to handle potential errors, such as unsupported coins or network issues.
MIT