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

@anemonedefi/sdk

v0.1.0

Published

TypeScript SDK for the Anemone Interest Rate Swap Protocol on Solana

Readme

Anemone SDK

TypeScript SDK for the Anemone Interest Rate Swap protocol on Solana.

Anemone lets traders take fixed vs. variable rate positions on Kamino K-Lend yields, while LPs earn the base lending rate with their capital always deployed.


Installation

npm install @anemone/sdk

Quick start

import { Connection } from "@solana/web3.js";
import { Anemone } from "@anemone/sdk";

const connection = new Connection("https://api.mainnet-beta.solana.com");

// Read-only (no wallet needed)
const sdk = new Anemone({ connection });

// With a wallet (required to send transactions)
const sdk = new Anemone({ connection, wallet });

wallet is an AnchorWallet (Phantom, Wallet Adapter, or anything that implements signTransaction + signAllTransactions).

The SDK groups instructions by role:

| Namespace | Instructions | |---|---| | sdk.query | protocol, markets, positions (read-only) | | sdk.admin | initializeProtocol, createMarket, setKeeper, pauseProtocol, unpauseProtocol, setRateIndexOracle | | sdk.lp | depositLiquidity, requestWithdrawal | | sdk.keeper | updateRateIndex, syncKaminoYield, depositToKamino, withdrawFromKamino | | sdk.trader | openSwap, addCollateral, settlePeriod, closePositionEarly, claimMatured, liquidatePosition |


Reading on-chain state

const protocol = await sdk.query.protocol.fetch();
const markets = await sdk.query.markets.fetchAll();

const market = await sdk.query.markets.fetchByReserveAndTenor(
  KAMINO_USDC_RESERVE,
  BigInt(TENOR_30_DAYS)
);

// LP position
const lpPosition = await sdk.query.positions.fetchLpPosition(
  wallet.publicKey.toBase58(),
  market.publicKey
);

// Swap position (trader+market+nonce)
const swap = await sdk.query.positions.fetchSwapPosition(swapPositionAddress);

preInstructions — bundling Kamino refresh

Most Kamino-touching instructions accept an optional preInstructions: TransactionInstruction[]. The typical pattern is to bundle a Kamino refresh_reserve so the program reads post-accrual values:

import { TransactionInstruction } from "@solana/web3.js";

// Build a Kamino refresh_reserve instruction (Anchor discriminator)
const refresh = refreshReserveIx({ /* reserve, lendingMarket, scopePrices, kaminoProgram */ });

await sdk.keeper.updateRateIndex.execute({
  keeper: wallet.publicKey,
  underlyingReserve: new PublicKey(KAMINO_USDC_RESERVE),
  tenorSeconds: BigInt(TENOR_30_DAYS),
  kaminoReserve: new PublicKey(KAMINO_USDC_RESERVE),
  preInstructions: [refresh], // atomic: refresh then read
});

Use cases that accept preInstructions: updateRateIndex, syncKaminoYield, depositToKamino, withdrawFromKamino, requestWithdrawal, closePositionEarly, claimMatured, liquidatePosition.

Without a fresh refresh, the program may reject with StaleOracle or InvalidRateIndex.


LP operations

Deposit liquidity

const { signature, lpPositionAddress } = await sdk.lp.depositLiquidity.execute({
  depositor:      wallet.publicKey,
  market:         new PublicKey(market.publicKey),
  underlyingMint: new PublicKey(USDC_MINT),
  lpMint:         new PublicKey(market.lpMint),
  lpVault:        new PublicKey(market.lpVault),
  amount:         100_000_000n, // 100 USDC
});

Request withdrawal

Single-shot: burns shares, redeems Kamino shortfall if needed, sends USDC back. All Kamino accounts are required even when no shortfall fires.

const { signature } = await sdk.lp.requestWithdrawal.execute({
  withdrawer:    wallet.publicKey,
  market:        new PublicKey(market.publicKey),
  underlyingMint: new PublicKey(USDC_MINT),
  lpMint:        new PublicKey(market.lpMint),
  lpVault:       new PublicKey(market.lpVault),
  treasury:      new PublicKey(protocol.treasury),
  sharesToBurn:  lpPosition.shares,
  // Kamino redeem-on-shortfall accounts:
  kaminoReserve, kaminoLendingMarket, kaminoLendingMarketAuthority,
  reserveLiquidityMint, reserveLiquiditySupply, reserveCollateralMint,
  collateralTokenProgram, liquidityTokenProgram,
  preInstructions: [refresh],
});

Trader operations

Open a swap

import { SwapDirection } from "@anemone/sdk";

const { signature, swapPositionAddress } = await sdk.trader.openSwap.execute({
  trader:          wallet.publicKey,
  market:          new PublicKey(market.publicKey),
  underlyingMint:  new PublicKey(USDC_MINT),
  treasury:        new PublicKey(protocol.treasury),
  collateralVault: new PublicKey(market.collateralVault),
  direction:       SwapDirection.PayFixed, // or ReceiveFixed
  notional:        100_000_000n,            // 100 USDC
  nonce:           1,                        // unique per (trader, market)
  maxRateBps:      1500n,                    // PayFixed slippage cap
  minRateBps:      0n,                       // ReceiveFixed slippage floor
});

Add collateral

await sdk.trader.addCollateral.execute({
  owner:           wallet.publicKey,
  market:          new PublicKey(market.publicKey),
  underlyingMint:  new PublicKey(USDC_MINT),
  collateralVault: new PublicKey(market.collateralVault),
  nonce:           1,
  amount:          50_000_000n, // 50 USDC
});

Settle period

Permissionless — anyone can call once next_settlement_ts has passed. Pays the period's PnL between lp_vault and collateral_vault.

await sdk.trader.settlePeriod.execute({
  caller:          wallet.publicKey,
  market:          new PublicKey(market.publicKey),
  swapPosition:    swapPositionAddress,
  underlyingMint:  new PublicKey(USDC_MINT),
  lpVault:         new PublicKey(market.lpVault),
  collateralVault: new PublicKey(market.collateralVault),
});

Close early

Pays the early-close fee + final MtM, releases remaining collateral.

await sdk.trader.closePositionEarly.execute({
  owner:           wallet.publicKey,
  market:          new PublicKey(market.publicKey),
  swapPosition:    swapPositionAddress,
  underlyingMint:  new PublicKey(USDC_MINT),
  lpVault:         new PublicKey(market.lpVault),
  collateralVault: new PublicKey(market.collateralVault),
  treasury:        new PublicKey(protocol.treasury),
  // Kamino redeem-on-shortfall accounts:
  kaminoReserve, kaminoLendingMarket, kaminoLendingMarketAuthority,
  reserveLiquidityMint, reserveLiquiditySupply, reserveCollateralMint,
  collateralTokenProgram, liquidityTokenProgram,
  preInstructions: [refresh],
});

Claim matured

Only valid after maturity_timestamp.

await sdk.trader.claimMatured.execute({
  owner:           wallet.publicKey,
  market:          new PublicKey(market.publicKey),
  swapPosition:    swapPositionAddress,
  underlyingMint:  new PublicKey(USDC_MINT),
  lpVault:         new PublicKey(market.lpVault),
  collateralVault: new PublicKey(market.collateralVault),
  // ...Kamino accounts as in closePositionEarly
});

Liquidate

Permissionless — any underwater position (collateral < maintenance margin) can be liquidated. Liquidation fee splits 1/3 to treasury, 2/3 to liquidator.

await sdk.trader.liquidatePosition.execute({
  liquidator:      wallet.publicKey,
  owner:           positionOwner,
  market:          new PublicKey(market.publicKey),
  swapPosition:    swapPositionAddress,
  underlyingMint:  new PublicKey(USDC_MINT),
  lpVault:         new PublicKey(market.lpVault),
  collateralVault: new PublicKey(market.collateralVault),
  treasury:        new PublicKey(protocol.treasury),
  // ...Kamino accounts
});

Admin operations

Initialize protocol

const { signature, protocolStateAddress } = await sdk.admin.initializeProtocol.execute({
  authority: wallet.publicKey,
  treasury:  treasuryAta,
  // fees are optional — defaults match the protocol spec
});

Create market

const { signature, marketAddress } = await sdk.admin.createMarket.execute({
  authority:           wallet.publicKey,
  underlyingReserve:   new PublicKey(KAMINO_USDC_RESERVE),
  underlyingProtocol:  new PublicKey(KAMINO_PROGRAM_ID),
  underlyingMint:      new PublicKey(USDC_MINT),
  kaminoCollateralMint: kaminoKUsdcMint, // = reserve.collateral.mint_pubkey
  tenorSeconds:        BigInt(TENOR_30_DAYS),
  settlementPeriodSeconds: BigInt(SECONDS_PER_DAY),
});

Pause / unpause

paused blocks new open_swap and deposit_liquidity. Settlements and closes still work.

await sdk.admin.pauseProtocol.execute({ authority: wallet.publicKey });
await sdk.admin.unpauseProtocol.execute({ authority: wallet.publicKey });

Set keeper

Rotate the address allowed to call update_rate_index, deposit_to_kamino, withdraw_from_kamino.

await sdk.admin.setKeeper.execute({
  authority: wallet.publicKey,
  newKeeper: keeperBotPubkey,
});

Set rate index oracle (dev-tools only)

Forces market.current_rate_index to a specific value. Only available in builds with the dev-tools feature flag (devnet/localnet/surfpool); excluded from mainnet builds. Used by tests to drive specific rate states; production uses update_rate_index reading from Kamino.

await sdk.admin.setRateIndexOracle.execute({
  authority:  wallet.publicKey,
  market:     new PublicKey(market.publicKey),
  rateIndex:  newIndexValue,
});

Keeper operations

The keeper bot keeps market state fresh and manages Kamino capital deployment.

// Pull Kamino's bsf into market.current_rate_index (cron every ~3 min)
await sdk.keeper.updateRateIndex.execute({
  keeper:            wallet.publicKey,
  underlyingReserve: new PublicKey(KAMINO_USDC_RESERVE),
  tenorSeconds:      BigInt(TENOR_30_DAYS),
  kaminoReserve:     new PublicKey(KAMINO_USDC_RESERVE),
  preInstructions:   [refresh],
});

// Sync NAV — credits Kamino yield delta into lp_nav
await sdk.keeper.syncKaminoYield.execute({
  underlyingReserve: new PublicKey(KAMINO_USDC_RESERVE),
  tenorSeconds:      BigInt(TENOR_30_DAYS),
  kaminoReserve, kaminoLendingMarket,
  pythOracle, switchboardPriceOracle, switchboardTwapOracle, scopePrices,
  preInstructions:   [refresh],
});

// Move idle lp_vault USDC into Kamino to earn yield
await sdk.keeper.depositToKamino.execute({
  keeper:            wallet.publicKey,
  underlyingReserve: new PublicKey(KAMINO_USDC_RESERVE),
  tenorSeconds:      BigInt(TENOR_30_DAYS),
  amount:            500_000_000n,
  // ...Kamino accounts
  preInstructions:   [refresh],
});

// Redeem k-tokens back to USDC (refill lp_vault before settlements)
await sdk.keeper.withdrawFromKamino.execute({
  keeper:            wallet.publicKey,
  underlyingReserve: new PublicKey(KAMINO_USDC_RESERVE),
  tenorSeconds:      BigInt(TENOR_30_DAYS),
  collateralAmount:  kTokenAmount,
  // ...Kamino accounts
  preInstructions:   [refresh],
});

Constants

import {
  ANEMONE_PROGRAM_ID,
  KAMINO_PROGRAM_ID,
  KAMINO_USDC_RESERVE,
  USDC_MINT,
  USDC_DECIMALS,
  LP_MINT_DECIMALS,
  TENOR_30_DAYS,
  TENOR_90_DAYS,
  SECONDS_PER_DAY,
  DEFAULT_PROTOCOL_FEE_BPS,
  DEFAULT_OPENING_FEE_BPS,
  DEFAULT_LIQUIDATION_FEE_BPS,
  DEFAULT_WITHDRAWAL_FEE_BPS,
  DEFAULT_EARLY_CLOSE_FEE_BPS,
  DEFAULT_MAX_UTILIZATION_BPS,
  DEFAULT_BASE_SPREAD_BPS,
  BPS_DENOMINATOR,
  KAMINO_MAX_STALE_SLOTS,
  SEEDS,
} from "@anemone/sdk";

PDA derivation

import { PdaDeriver } from "@anemone/sdk";
import { PublicKey } from "@solana/web3.js";

const { address: protocolState } = await PdaDeriver.protocol();

const { address: market } = await PdaDeriver.market(
  new PublicKey(KAMINO_USDC_RESERVE),
  BigInt(TENOR_30_DAYS)
);

const { address: lpPosition } = await PdaDeriver.lpPosition(
  ownerPublicKey,
  marketPublicKey
);

// Swap position: seeds are [b"swap", trader, market, nonce]
const { address: swapPosition } = await PdaDeriver.swapPosition(
  traderPublicKey,
  marketPublicKey,
  /* nonce */ 1
);

const { address: lpVault }         = await PdaDeriver.lpVault(marketPublicKey);
const { address: collateralVault } = await PdaDeriver.collateralVault(marketPublicKey);
const { address: lpMint }          = await PdaDeriver.lpMint(marketPublicKey);
const { address: kaminoDeposit }   = await PdaDeriver.kaminoDepositAccount(marketPublicKey);

Development

npm install
npm test                # 99 unit tests (mocked program, IDL conformance)
npm run test:e2e        # 37 E2E tests against surfpool — see e2e/README.md
npm run build           # compile to dist/
npx tsc --noEmit        # type-check only

E2E suite (surfpool)

The E2E suite runs against surfpool, a mainnet-fork validator that lazily forks Kamino's USDC reserve, lending market, and Scope prices. See e2e/README.md for setup; the short version:

# In anemone/
yarn surfpool          # start mainnet fork on 127.0.0.1:8899
yarn ts-node scripts/setup-surfpool.ts  # deploy program + init protocol/market

# In SDK/
npm run test:e2e

15 files, 37 tests, ~15 minutes total runtime. Coverage:

| Category | Files | |---|---| | Read-only queries | protocol-read | | LP lifecycle | lp-lifecycle, kamino-deposit | | Trader lifecycle | swap-lifecycle, trader-collateral, settle-period, claim-matured, multi-settlement | | Liquidation | liquidation (plumbing), liquidation-positive (1/3 vs 2/3 split), liquidation-organic (no forged state) | | Admin / keeper | admin-lifecycle, keeper-ops | | Negative paths | negative-paths (6 reverts) | | Pre-mainnet hardening | pre-mainnet (pause guards, keeper rotation, Token-2022, slippage) |

The organic liquidation, multi-settlement, and pre-mainnet tests need the on-chain program built with the dev-tools feature so set_rate_index_oracle is exposed. Mainnet builds (--no-default-features) omit it.


Program

| Network | Program ID | |---------|-----------| | Mainnet | KQs6ci5FtedFKPVJThAZSMMXyosK4TvnF7kcDSx5Jwd |