TypeScript SDK

Overview

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.

Key Features

  • 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.

Installation

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)

Usage

Initialize the SDK

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 });

Mint Meta Coins (Deposit)

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.

Example: Mint mUSD with USDC

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 (Withdraw)

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.

Example: Burn mUSD to Withdraw USDC

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();

Fetch Vault Data

Retrieve data about a Meta Vault, including deposit caps, total deposits, fees, and priorities for each supported asset.

Example: Fetch mUSD Vault Data

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 Dynamic Withdrawal Fee

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)

Example: Calculate Withdrawal Fee for mUSD

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();

Calculate Maximum Deposit

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.

Example: Calculate Maximum USDC Deposit for mUSD Vault

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();

Calculate Maximum Withdrawal

Determine the maximum amount of an asset you can withdraw from a Meta Vault, accounting for the dynamic withdrawal fee.

Example: Calculate Maximum USDC Withdrawal from mUSD Vault

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();

Calculate Mint and Burn Amounts

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);
}

Fetch Coin Prices

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.

Example 1: Fetch SUI Price

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();

Example 2: Fetch mSUI Price

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();

Example 3: Fetch LST Price (e.g., AF_SUI)

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();

Notes

  • 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.

License

MIT

Last updated