npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aspan/sdk

v0.1.8

Published

TypeScript SDK for Aspan Protocol - LST-backed stablecoin on BNB Chain

Downloads

311

Readme

@aspan/sdk

TypeScript SDK for Aspan Protocol - LST-backed stablecoin on BNB Chain.

Installation

npm install @aspan/sdk
# or
pnpm add @aspan/sdk

Contract Addresses (BSC Mainnet)

| Contract | Address | |----------|---------| | Diamond (Main Entry) | 0x10d25Ae0690533e0BA9E64EC7ae77dbD4fE8A46f | | ApUSD | 0x1977097E2E5697A6DD91b6732F368a14F50f6B3d | | XBNB | 0xB78eB4d5928bAb158Eb23c3154544084cD2661d5 | | SApUSD | 0xE2BE739C4aA4126ee72D612d9548C38B1B0e5A1b | | SlisBNBAdapter | 0x1B0b8001624CC67031f1c30cCDC12fBdD5752376 |

Quick Start

Read-Only Client (Query Data)

import { createAspanReadClient, formatAmount, formatCR } from "@aspan/sdk";

const DIAMOND = "0x10d25Ae0690533e0BA9E64EC7ae77dbD4fE8A46f";
const client = createAspanReadClient(DIAMOND, "https://bsc-dataseed.binance.org/");

const stats = await client.getProtocolStats();
console.log("TVL:", formatAmount(stats.tvlInUSD), "USD");
console.log("CR:", formatCR(stats.collateralRatio));

Write Client - Browser (React/wagmi)

import { AspanClient } from "@aspan/sdk";
import { useWalletClient } from "wagmi";

const DIAMOND = "0x10d25Ae0690533e0BA9E64EC7ae77dbD4fE8A46f";

function MyComponent() {
  const { data: walletClient } = useWalletClient();

  const getClient = () => {
    if (!walletClient) return null;
    return new AspanClient({
      diamondAddress: DIAMOND,
      walletClient: walletClient,  // Pass wagmi's walletClient
    });
  };

  const handleMint = async () => {
    const client = getClient();
    if (!client) return;
    
    const hash = await client.mintApUSD({
      lstToken: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B",
      lstAmount: parseAmount("1"),
    });
    console.log("Tx hash:", hash);
  };
}

Write Client - Node.js / Server

import { createAspanClient, parseAmount } from "@aspan/sdk";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount("0x...");
const client = createAspanClient(DIAMOND, account);

const hash = await client.mintApUSD({
  lstToken: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B",
  lstAmount: parseAmount("1"),
});

User Flows

Flow 1: Mint apUSD (Stablecoin)

User deposits LST (e.g., slisBNB) to mint apUSD stablecoin.

Browser (React/wagmi)

import { AspanClient, parseAmount } from "@aspan/sdk";
import { useWalletClient } from "wagmi";

const DIAMOND = "0x10d25Ae0690533e0BA9E64EC7ae77dbD4fE8A46f";
const SLISBNB = "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B";

function MintComponent() {
  const { data: walletClient } = useWalletClient();

  const handleMint = async () => {
    if (!walletClient) return;

    const client = new AspanClient({
      diamondAddress: DIAMOND,
      walletClient,
    });

    const lstAmount = parseAmount("10"); // 10 slisBNB

    // Step 1: Check LST is supported
    const isSupported = await client.isLSTSupported(SLISBNB);
    if (!isSupported) throw new Error("LST not supported");

    // Step 2: Check current fees
    const fees = await client.getCurrentFees();
    if (fees.apUSDMintDisabled) throw new Error("Minting disabled");

    // Step 3: Approve LST (use wagmi's useWriteContract or viem)
    // ...

    // Step 4: Calculate minOut for slippage protection (e.g., 0.5% slippage)
    const expectedApUSD = lstAmount; // Simplified, use actual calculation
    const minOut = expectedApUSD * 995n / 1000n; // 0.5% slippage

    // Step 5: Mint apUSD
    const hash = await client.mintApUSD({ lstToken: SLISBNB, lstAmount, minOut });
    const receipt = await client.waitForTransaction(hash);
    console.log("Minted apUSD:", receipt.status);
  };
}

Node.js / Server

import { createAspanClient, parseAmount } from "@aspan/sdk";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount("0x...");
const client = createAspanClient(DIAMOND, account);

const SLISBNB = "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B";
const lstAmount = parseAmount("10"); // 10 slisBNB

// Step 1: Check LST is supported
const isSupported = await client.isLSTSupported(SLISBNB);
if (!isSupported) throw new Error("LST not supported");

// Step 2: Check current fees
const fees = await client.getCurrentFees();
console.log("Mint fee:", fees.apUSDMintFee / 100, "%");
if (fees.apUSDMintDisabled) throw new Error("Minting disabled in current CR");

// Step 3: Approve LST spending (use viem directly)
// await walletClient.writeContract({
//   address: SLISBNB,
//   abi: erc20Abi,
//   functionName: "approve",
//   args: [DIAMOND, lstAmount],
// });

// Step 4: Mint apUSD with slippage protection
const minOut = lstAmount * 995n / 1000n; // 0.5% slippage tolerance
const hash = await client.mintApUSD({ lstToken: SLISBNB, lstAmount, minOut });
const receipt = await client.waitForTransaction(hash);
console.log("Minted apUSD:", receipt.status);

Flow 2: Redeem apUSD for LST

User burns apUSD to get back LST.

const apUSDAmount = parseAmount("5000"); // 5000 apUSD

// Step 1: Check available LST liquidity
const collateral = await client.getLSTCollateral(SLISBNB);
const lstPrice = await client.getLSTPriceUSD(SLISBNB);
const maxRedeemable = (collateral * lstPrice) / parseAmount("1");
console.log("Max redeemable:", formatAmount(maxRedeemable), "USD");

// Step 2: Approve apUSD spending (use viem directly)

// Step 3: Calculate expected LST output and set minOut
const expectedLST = (apUSDAmount * parseAmount("1")) / lstPrice;
const minOut = expectedLST * 995n / 1000n; // 0.5% slippage

// Step 4: Redeem with slippage protection
const hash = await client.redeemApUSD({ lstToken: SLISBNB, apUSDAmount, minOut });
await client.waitForTransaction(hash);

Flow 3: Mint xBNB (Leveraged Long)

User deposits LST to mint xBNB, a leveraged long position on BNB.

// Step 1: Check xBNB price and leverage
const xBNBPrice = await client.getXBNBPriceBNB();
const leverage = await client.getEffectiveLeverage();
console.log("xBNB Price:", formatAmount(xBNBPrice), "BNB");
console.log("Effective Leverage:", formatAmount(leverage), "x");

// Step 2: Check if xBNB is underwater (price = 0)
if (xBNBPrice === 0n) {
  throw new Error("xBNB underwater - cannot mint");
}

// Step 3: Approve LST, then mint xBNB with slippage protection
const minOut = 0n; // Set appropriate minOut based on expected xBNB output
const hash = await client.mintXBNB({ lstToken: SLISBNB, lstAmount, minOut });
await client.waitForTransaction(hash);

Flow 4: Redeem xBNB for LST

User burns xBNB to get back LST.

const xBNBAmount = parseAmount("100"); // 100 xBNB

// Step 1: Check xBNB price (ensure not underwater)
const xBNBPrice = await client.getXBNBPriceBNB();
if (xBNBPrice === 0n) {
  throw new Error("xBNB is underwater - redemption may result in 0 LST");
}

// Step 2: Check current fees
const fees = await client.getCurrentFees();
console.log("xBNB Redeem fee:", fees.xBNBRedeemFee / 100, "%");

// Step 3: Check available LST liquidity
const collateral = await client.getLSTCollateral(SLISBNB);
console.log("Available collateral:", formatAmount(collateral));

// Step 4: Approve xBNB spending (use viem directly)
// ...

// Step 5: Calculate expected LST and set minOut for slippage protection
const expectedLST = (xBNBAmount * xBNBPrice) / parseAmount("1");
const minOut = expectedLST * 995n / 1000n; // 0.5% slippage

// Step 6: Redeem xBNB
const hash = await client.redeemXBNB({ lstToken: SLISBNB, xBNBAmount, minOut });
await client.waitForTransaction(hash);

Flow 5: Stake apUSD to Earn Yield (sApUSD)

User deposits apUSD to stability pool to earn LST yield.

// Step 1: Check stability pool stats
const poolStats = await client.getStabilityPoolStats();
console.log("Total Staked:", formatAmount(poolStats.totalStaked));
console.log("Exchange Rate:", formatAmount(poolStats.exchangeRate));

// Step 2: Preview deposit
const depositAmount = parseAmount("1000");
const expectedShares = await client.previewDeposit(depositAmount);
console.log("Expected shares:", formatAmount(expectedShares));

// Step 3: Approve apUSD, then deposit
const hash = await client.deposit({ apUSDAmount: depositAmount });
await client.waitForTransaction(hash);

// Step 4: Check position
const position = await client.getUserStabilityPoolPosition(account.address);
console.log("Shares:", formatAmount(position.shares));
console.log("Balance (incl. yield):", formatAmount(position.balance));

Flow 6: Withdraw from Stability Pool

User withdraws their staked apUSD plus accumulated yield.

// Step 1: Get user's shares
const shares = await client.getShares(account.address);

// Step 2: Preview redemption
const expectedAssets = await client.previewRedeem(shares);
console.log("Expected apUSD:", formatAmount(expectedAssets));

// Step 3: Approve sApUSD shares transfer
// const sApUSD = await client.getSApUSD();

// Step 4: Withdraw all shares
const hash = await client.withdraw({ shares });
await client.waitForTransaction(hash);

// Or withdraw specific amount of apUSD:
// const hash = await client.withdrawAssets({ assets: parseAmount("500") });

Flow 7: Manual Yield Harvest

Anyone can trigger yield harvest to distribute pending LST yield.

// Step 1: Check pending yield
const yieldStats = await client.getYieldStats();
console.log("Pending yield:", formatAmount(yieldStats.pendingYield), "USD");
console.log("Preview harvest:", formatAmount(yieldStats.previewedHarvest), "USD");

// Step 2: Harvest (if there's yield)
if (yieldStats.pendingYield + yieldStats.previewedHarvest > 0n) {
  const hash = await client.harvestYield();
  await client.waitForTransaction(hash);
}

Protocol Metrics Guide

Based on protocol-analysis.md, here's how to read all key metrics:

Core Metrics (Section 3: Core Math Model)

| Metric | SDK Method | Description | |--------|------------|-------------| | TVL | getTVLInUSD() | Total Value Locked in USD | | TVL (BNB) | getTVLInBNB() | TVL in BNB terms | | apUSD Supply | getApUSDSupply() | Total apUSD minted | | xBNB Supply | getXBNBSupply() | Total xBNB minted |

const stats = await client.getProtocolStats();
// stats.tvlInUSD - TVL = sum of all LST collateral value
// stats.apUSDSupply - stable portion of the pool
// stats.xBNBSupply - leveraged long portion

xBNB Price (Section 3.3 & 4)

| Metric | SDK Method | Formula | |--------|------------|---------| | xBNB Price (BNB) | getXBNBPriceBNB() | (TVL_BNB - apUSD_value_BNB) / xBNB_supply | | xBNB Price (USD) | getXBNBPriceUSD() | xBNB_price_BNB * BNB_price_USD |

const xBNBPriceBNB = await client.getXBNBPriceBNB();
const xBNBPriceUSD = await client.getXBNBPriceUSD();
// Price = 0 means xBNB is "underwater" (TVL <= apUSD value)

Collateral Ratio (Section 7)

| Metric | SDK Method | Formula | |--------|------------|---------| | CR | getCollateralRatio() | (TVL_USD / apUSD_supply) * 10000 (BPS) |

const cr = await client.getCollateralRatio();
// CR in BPS: 15000 = 150%, 13000 = 130%, 10000 = 100%
console.log("CR:", Number(cr) / 100, "%");

Effective Leverage (Section 5)

| Metric | SDK Method | Formula | |--------|------------|---------| | Leverage | getEffectiveLeverage() | TVL / xBNB_market_cap |

const leverage = await client.getEffectiveLeverage();
// 1e18 = 1x, 2e18 = 2x leverage
console.log("Leverage:", formatAmount(leverage), "x");

Stability Mode (Section 8)

| Mode | CR Range | Description | |------|----------|-------------| | Normal (0) | CR >= 150% | Standard operations | | Mode 1 (1) | 130% <= CR < 150% | Fee adjustments active | | Mode 2 (2) | CR < 130% | Forced conversion possible |

const mode = await client.getStabilityMode();
// mode.mode: 0=Normal, 1=StabilityMode1, 2=StabilityMode2
// mode.currentCR: Current CR in BPS

const mode2Info = await client.canTriggerStabilityMode2();
// mode2Info.canTrigger: true if CR < 130%
// mode2Info.potentialConversion: apUSD that would be converted

Fee Tiers (Section 8.2)

| Mode | apUSD Mint | apUSD Redeem | xBNB Mint | xBNB Redeem | |------|------------|--------------|-----------|-------------| | Normal | 0.2% | 0.2% | 1% | 1% | | Mode 1 | 0.3% | 0.1% | 0.25% | 4% | | Mode 2 | Disabled | 0% | 0% | 8% |

const fees = await client.getCurrentFees();
// fees.currentCR - Current CR
// fees.tierMinCR - Tier threshold
// fees.apUSDMintFee - in BPS (20 = 0.2%)
// fees.apUSDMintDisabled - true in Mode 2

Stability Pool / Yield (Section 6)

| Metric | SDK Method | Description | |--------|------------|-------------| | Total Staked | getTotalStaked() | apUSD in stability pool | | Exchange Rate | getExchangeRate() | sApUSD to apUSD ratio | | Pending Yield | getPendingYield() | Yield waiting to be distributed | | Total Generated | getTotalYieldGenerated() | All-time yield |

const poolStats = await client.getStabilityPoolStats();
const yieldStats = await client.getYieldStats();

// APY calculation (Section 6.2-6.3)
// APY = LST_yield_rate * (TVL / staked_apUSD)
const amplification = stats.tvlInUSD / poolStats.totalStaked;
const estimatedAPY = 0.08 * Number(amplification); // Assuming 8% LST yield

LST Information

// Get all supported LSTs
const lsts = await client.getSupportedLSTs();

for (const lst of lsts) {
  const info = await client.getLSTInfo(lst);
  const price = await client.getLSTPriceUSD(lst);
  const collateral = await client.getLSTCollateral(lst);
  const yieldInfo = await client.getLSTYieldInfo(lst);

  console.log(`LST: ${lst}`);
  console.log(`  Accepted: ${info.isAccepted}`);
  console.log(`  Collateral: ${formatAmount(collateral)}`);
  console.log(`  Price: $${formatAmount(price)}`);
  console.log(`  Exchange Rate: ${formatAmount(yieldInfo.lastExchangeRate)}`);
}

Oracle / Prices

const bnbPrice = await client.getBNBPriceUSD();
console.log("BNB Price:", formatPriceUSD(bnbPrice));
// Note: BNB price is 8 decimals (Chainlink format)

const lstPrice = await client.getLSTPriceUSD(SLISBNB);
console.log("LST Price:", formatAmount(lstPrice), "USD");
// Note: LST price is 18 decimals

Complete Dashboard Example

import {
  createAspanReadClient,
  formatAmount,
  formatCR,
  formatFeeBPS,
  formatPriceUSD,
} from "@aspan/sdk";

const DIAMOND = "0xa67e91ebbb709516c563bcf1d9dae355aaf6d2ef";
const client = createAspanReadClient(DIAMOND);

async function displayDashboard() {
  // === Protocol Overview ===
  const stats = await client.getProtocolStats();
  const mode = await client.getStabilityMode();
  const fees = await client.getCurrentFees();

  console.log("=== Aspan Protocol Dashboard ===");
  console.log(`TVL: $${formatAmount(stats.tvlInUSD)}`);
  console.log(`CR: ${formatCR(stats.collateralRatio)}`);
  console.log(`Stability Mode: ${mode.mode === 0 ? "Normal" : `Mode ${mode.mode}`}`);
  console.log(`Effective Leverage: ${formatAmount(stats.effectiveLeverage)}x`);

  // === Token Stats ===
  console.log("\n=== Tokens ===");
  console.log(`apUSD Supply: ${formatAmount(stats.apUSDSupply)}`);
  console.log(`xBNB Supply: ${formatAmount(stats.xBNBSupply)}`);
  console.log(`xBNB Price: ${formatAmount(stats.xBNBPriceBNB)} BNB`);

  // === Current Fees ===
  console.log("\n=== Current Fees ===");
  console.log(`apUSD Mint: ${formatFeeBPS(fees.apUSDMintFee)}${fees.apUSDMintDisabled ? " (DISABLED)" : ""}`);
  console.log(`apUSD Redeem: ${formatFeeBPS(fees.apUSDRedeemFee)}`);
  console.log(`xBNB Mint: ${formatFeeBPS(fees.xBNBMintFee)}`);
  console.log(`xBNB Redeem: ${formatFeeBPS(fees.xBNBRedeemFee)}`);

  // === Stability Pool ===
  const poolStats = await client.getStabilityPoolStats();
  const yieldStats = await client.getYieldStats();

  console.log("\n=== Stability Pool (sApUSD) ===");
  console.log(`Total Staked: ${formatAmount(poolStats.totalStaked)} apUSD`);
  console.log(`Exchange Rate: ${formatAmount(poolStats.exchangeRate)}`);
  console.log(`Pending Yield: $${formatAmount(yieldStats.pendingYield)}`);
  console.log(`Total Yield Generated: $${formatAmount(yieldStats.totalYieldGenerated)}`);

  // === LST Collateral ===
  const lsts = await client.getSupportedLSTs();
  console.log("\n=== LST Collateral ===");
  for (const lst of lsts) {
    const collateral = await client.getLSTCollateral(lst);
    const price = await client.getLSTPriceUSD(lst);
    const value = (collateral * price) / 10n ** 18n;
    console.log(`${lst.slice(0, 10)}...: ${formatAmount(collateral)} ($${formatAmount(value)})`);
  }
}

displayDashboard();

API Reference

Client Configuration

| Option | Type | Required | Description | |--------|------|----------|-------------| | diamondAddress | Address | ✅ | Diamond contract address | | chain | Chain | ❌ | Chain config (default: BSC Mainnet) | | rpcUrl | string | ❌ | RPC URL (default: BSC public RPC) | | walletClient | WalletClient | ⚠️ | For browser/wagmi (required if no account) | | account | Account | ⚠️ | For Node.js (required if no walletClient) |

⚠️ Write client requires either walletClient (browser) or account (Node.js)

View Functions

| Category | Methods | |----------|---------| | Stats | getProtocolStats(), getStabilityPoolStats(), getYieldStats() | | Pool | getTVLInBNB(), getTVLInUSD(), getCollateralRatio(), getXBNBPriceBNB(), getXBNBPriceUSD(), getEffectiveLeverage(), getApUSDSupply(), getXBNBSupply(), getLSTCollateral(), getCurrentFees() | | Stability Pool | getShares(), getBalance(), getUserStabilityPoolPosition(), getExchangeRate(), getTotalStaked(), previewDeposit(), previewRedeem(), getPendingYield() | | Yield | getTotalYieldGenerated(), getLSTYieldInfo(), getMinHarvestInterval(), getLastHarvestTimestamp(), previewHarvest() | | Oracle | getBNBPriceUSD(), getLSTPriceUSD(), getLSTInfo(), getSupportedLSTs(), isLSTSupported(), getBNBPriceFeed(), getOracleBounds() | | Config | getTokens(), getSApUSD(), getStabilityPool(), getTreasury(), getFeeTierCount(), getFeeTier(), getCurrentFeeTier(), getMaxPriceAge(), getMinDepositPeriod(), isPaused() | | Stability Mode | getStabilityMode(), canTriggerStabilityMode2() | | Ownership | getOwner() |

Write Functions

| Category | Methods | |----------|---------| | Pool | mintApUSD(), redeemApUSD(), mintXBNB(), redeemXBNB() | | Stability Pool | deposit(), withdraw(), withdrawAssets(), harvestYield() |


Utility Functions

import {
  formatAmount,     // bigint -> "1234.5678"
  parseAmount,      // "1234.5678" -> bigint
  formatFeeBPS,     // 25 -> "0.25%"
  formatCR,         // 15000n -> "150%"
  formatPriceUSD,   // 58325000000n -> "$583.25"
  calculateAPY,     // (oldRate, newRate, days) -> APY%
  PRECISION,        // 10^18
  BPS_PRECISION,    // 10000
  PRICE_PRECISION,  // 10^8
} from "@aspan/sdk";

Testnet

import {
  createAspanTestnetReadClient,
  createAspanTestnetClient,
} from "@aspan/sdk";

const client = createAspanTestnetReadClient("0x...");
const writeClient = createAspanTestnetClient("0x...", account);

License

MIT