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

@baseline-markets/sdk

v1.3.0

Published

TypeScript SDK for Baseline — the end-to-end asset issuance protocol where tokens own their liquidity.

Readme

@baseline-markets/sdk

A typed TypeScript SDK for interacting with Baseline Protocol contracts via viem.

Baseline is an onchain AMM for tokens with built-in liquidity — @baseline-markets/sdk exposes a single BaselineSDK class covering token launches, swaps, borrowing, leverage, staking, and rewards.

Install

npm install @baseline-markets/sdk viem
# or: bun add @baseline-markets/sdk viem

viem is a peer dependency — bring your own.

Quickstart

import { BaselineSDK } from '@baseline-markets/sdk';
import { createPublicClient, createWalletClient, http, custom } from 'viem';
import { base } from 'viem/chains';

const publicClient = createPublicClient({
  chain: base,
  transport: http(),
});

// Wallet client is optional — only needed for write actions
const walletClient = createWalletClient({
  chain: base,
  transport: custom(window.ethereum),
});

const sdk = new BaselineSDK(publicClient, walletClient);

Each SDK instance is bound to a single chain — the chain comes from publicClient.chain. To talk to a different chain, build a new publicClient (and walletClient if writing) for that chain and instantiate a new BaselineSDK. The SDK has no chainId parameter on its methods by design; chain selection lives in the clients you pass to the constructor. See Switching chains below for the React + wagmi pattern.

Read-only

const bToken = '0x...' as const;

const price   = await sdk.activePrice(bToken);
const reserve = await sdk.getReserve(bToken);
const quote   = await sdk.quoteBuyExactOut(bToken, 100n);

Swaps

// Buy exactly 100 bTokens, capped at `quote.amountIn` reserve in
const hash = await sdk.buyTokensExactOut(bToken, 100n, quote.amountIn, {
  confirmations: 1,
});

// Sell 100 bTokens, accept at least `minOut` reserve out
const hash2 = await sdk.sellTokensExactIn(bToken, 100n, minOut);

Borrow / leverage / stake

await sdk.deposit(bToken, collateral);
await sdk.borrow(bToken, debtAmount, recipient);

const leverageQuote = await sdk.quoteLeverage(bToken, collateralIn, leverageFactor);
await sdk.leverage(
  bToken,
  leverageQuote.targetCollateral,
  collateralIn,
  leverageQuote.maxSwapReservesIn,
);

await sdk.repay(bToken, reservesIn, recipient);
await sdk.claim(bToken);

See src/baseline-sdk.ts for the full method list.

Error handling

All write methods throw SDKError, a single error type with a .kind discriminator so you don't have to sniff messages:

import { SDKError } from '@baseline-markets/sdk';

try {
  await sdk.buyTokensExactOut(bToken, 100n, maxIn);
} catch (err) {
  if (err instanceof SDKError) {
    switch (err.kind) {
      case 'user_rejected':     // user cancelled in their wallet
      case 'insufficient_funds': // not enough native balance for gas
      case 'reverted':          // contract reverted (decoded reason in .message)
      case 'network':           // RPC/socket/timeout — retry-worthy
      case 'wallet':            // SDK misuse: no wallet, no account
      case 'unknown':           // anything else
    }
  }
}

The original viem error is preserved on err.cause if you need it.

React + wagmi

wagmi's usePublicClient / useWalletClient return viem clients, so they plug straight into BaselineSDK. Wrap construction in a hook and memoize — re-creating the SDK on every render is fine but wasteful.

import { useMemo } from 'react';
import { useChainId, usePublicClient, useWalletClient } from 'wagmi';
import { BaselineSDK } from '@baseline-markets/sdk';

export function useBaselineSDK(chainId?: number) {
  const walletChainId = useChainId();
  const targetChainId = chainId ?? walletChainId;

  const publicClient  = usePublicClient({ chainId: targetChainId });
  const { data: walletClient } = useWalletClient({ chainId: targetChainId });

  return useMemo(() => {
    if (!publicClient) return null;
    return new BaselineSDK(publicClient, walletClient ?? undefined);
  }, [publicClient, walletClient]);
}

useWalletClient() returns undefined until the user connects — the SDK still works for reads in that state, and sdk.hasWallet tells you whether write actions are available.

Switching chains

The SDK is single-chain: the chain is baked into publicClient, so a BaselineSDK instance can only talk to one network. When the user switches network, you need new clients and a new SDK.

With the hook above this is automatic — passing chainId to wagmi's usePublicClient/useWalletClient returns different client references per chain, the useMemo deps change, and a fresh BaselineSDK is constructed. You don't have to do anything special; just trust that:

  1. Chain change → new clients → new SDK. Construction is cheap (the SDK just holds client references and resolves a proxy address from the chain id), so don't try to skip the rebuild.
  2. Don't mix chains in one SDK. Never pass a publicClient for one chain and a walletClient for another — reads and writes will target different networks.
  3. Read across chains? Call the hook with an explicit chainId per component (e.g. useBaselineSDK(mainnet.id) and useBaselineSDK(base.id)) — you'll get two independent SDK instances, one per chain.

Reads with useQuery

import { useQuery } from '@tanstack/react-query';

function Price({ bToken }: { bToken: `0x${string}` }) {
  const sdk = useBaselineSDK();

  const { data: price } = useQuery({
    queryKey: ['baseline', 'activePrice', sdk?.chainId, bToken],
    queryFn: () => sdk!.activePrice(bToken),
    enabled: !!sdk,
  });

  return <div>{price?.toString()}</div>;
}

Include sdk.chainId in the query key so cached data is scoped per network.

Writes with useMutation

import { useMutation } from '@tanstack/react-query';
import { SDKError } from '@baseline-markets/sdk';

function BuyButton({ bToken, amount, maxIn }: {
  bToken: `0x${string}`;
  amount: bigint;
  maxIn: bigint;
}) {
  const sdk = useBaselineSDK();

  const buy = useMutation({
    mutationFn: () =>
      sdk!.buyTokensExactOut(bToken, amount, maxIn, { confirmations: 1 }),
    onError: (err) => {
      if (err instanceof SDKError && err.kind === 'user_rejected') return;
      // surface other kinds: insufficient_funds, reverted, network, ...
    },
  });

  return (
    <button
      disabled={!sdk?.hasWallet || buy.isPending}
      onClick={() => buy.mutate()}
    >
      {buy.isPending ? 'Confirming…' : 'Buy'}
    </button>
  );
}

The confirmations option resolves the promise only after the receipt reaches the requested confirmation count, so buy.isPending covers both the wallet prompt and the on-chain confirmation.

Configuration

BaselineSDK takes an optional third argument:

new BaselineSDK(publicClient, walletClient, {
  defaultUseNative: true,  // use native ETH paths by default where supported
});

Per-call options live on TxOpts:

await sdk.buyTokensExactOut(bToken, 100n, maxIn, {
  account: '0x...',           // override which address sends the tx
  confirmations: 2,           // wait for N confirmations before returning
  onSimulateError: (e) => {}, // hook for pre-simulation failures
});

Supported networks

  • Ethereum mainnet (mainnet, chain id 1)
  • Base (base, chain id 8453)

The SDK reads the chain from your publicClient and throws if it isn't one of the supported chains — no separate chain config needed.

import { supportedChainIds } from '@baseline-markets/sdk';

if (!supportedChainIds.includes(chainId)) {
  // unsupported network — prompt user to switch
}

Development

bun install
bun run build     # bundle ESM + CJS + .d.ts via tsup
bun test

License

MIT