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

deeppoolsdk

v5.0.0

Published

sdk for interacting with deep_pool on chain

Downloads

568

Readme

DeepPool SDK

TypeScript SDK for DeepPool — a constant-product pool protocol on Solana. 0.25% swap fee, 100% back to liquidity. Permanent LP locks on every deposit. Pools that only get deeper.

Install

pnpm add deeppoolsdk

Peer dependency: @solana/web3.js ^1.98.0

How It Works

1. Read pool state   →  getPool (RPC, or indexer-first with { indexer })
2. Get a quote       →  getSwapQuote (client-side, no RPC)
3. Build a tx        →  buildSwapTransaction
4. Sign and send     →  your wallet / keypair
5. Subscribe live    →  createIndexerBus (optional, indexer-backed)

Operations

Read

| Function | Description | |----------|-------------| | getPool(connection, tokenMint, config, options?) | Pool state by (config, mint). Indexer-first with RPC fallback when options.indexer is set. | | getPoolByAddress(connection, poolAddress, options?) | Pool state by PDA. Same indexer-first behavior. | | getPoolsForMint(connection, tokenMint) | Every pool for a mint, across all configs. RPC-only. | | getSwapQuote(solReserve, tokenReserve, amountIn, buy, transferFeeBps?) | Expected output, fee, price impact. Pure compute — no RPC. |

ReadOptions = { indexer?: string }. On any indexer failure (network, non-200, malformed) the call silently falls back to RPC.

Indexer-only Reads

These have no RPC equivalent — chain RPCs can't answer "all swaps for pool X since time T". They throw if the indexer is unreachable.

| Function | Description | |----------|-------------| | getSwapHistory({ indexer, poolId?, user?, tokenMint?, since?, before?, limit? }) | Filtered swap history. | | getLiquidityHistory({ indexer, poolId?, provider?, tokenMint?, isAdd?, since?, before?, limit? }) | Filtered add/remove history. |

Live Events

createIndexerBus(indexerUrl) opens a single WebSocket per process and dispatches typed frames to subscribers. Auto-reconnects on disconnect and gap-fills via REST so consumers see every event that landed during the disconnect window.

| Method | Description | |--------|-------------| | bus.on(kind, handler) | Subscribe to 'pool' \| 'swap' \| 'liquidity' \| 'reserves'. Returns unsubscribe. | | bus.onConnectionChange(handler) | 'connected' \| 'disconnected' transitions. | | bus.close() | Close socket and clear all handlers. |

Frames are a discriminated union — BroadcastFrame = { kind: 'pool', ...IndexerPoolRow } | { kind: 'swap', ...SwapRow } | ....

Pool Management

| Function | Description | |----------|-------------| | buildCreatePoolTransaction(connection, params) | Create pool with initial SOL + tokens. 80% LP to creator, 20% locked permanently. | | buildAddLiquidityTransaction(connection, params) | Proportional deposit. 92.5% LP to provider, 7.5% locked permanently. | | buildRemoveLiquidityTransaction(connection, params) | Burn LP tokens. Receive proportional SOL + tokens. Pool retains locked reserves. |

Trading

| Function | Description | |----------|-------------| | buildSwapTransaction(connection, params) | Buy (SOL→Token) or sell (Token→SOL). 0.25% fee compounds into pool. |

PDA Derivation

| Function | Description | |----------|-------------| | getPoolPda(config, tokenMint) | Pool state PDA (namespaced by config). | | getVaultPda(pool) | Token vault PDA. | | getLpMintPda(pool) | LP token mint PDA. | | getEventAuthorityPda() | Anchor emit_cpi! authority PDA. |

Events

| Function | Description | |----------|-------------| | parseEvents(connection, signature) | Decode PoolCreated, LiquidityAdded, LiquidityRemoved, SwapExecuted from a confirmed tx's inner instructions. |

Example — RPC Read

import { Connection } from '@solana/web3.js'
import { getPool, getSwapQuote, buildSwapTransaction, LAMPORTS_PER_SOL } from 'deeppoolsdk'

const connection = new Connection('https://api.devnet.solana.com')
const mint = 'YOUR_TOKEN_MINT'
const config = 'YOUR_CONFIG_PUBKEY'

const pool = await getPool(connection, mint, config)
if (!pool) throw new Error('pool not found')

const quote = getSwapQuote(pool.solReserve, pool.tokenReserve, 1 * LAMPORTS_PER_SOL, true)

const { transaction } = await buildSwapTransaction(connection, {
  user: walletAddress,
  tokenMint: mint,
  amountIn: 1 * LAMPORTS_PER_SOL,
  minimumOut: Math.floor(quote.amountOut * 0.99),
  buy: true,
})

Example — Indexer-First Read

import { getPool, getSwapHistory } from 'deeppoolsdk'

const indexer = process.env.NEXT_PUBLIC_INDEXER_URL // e.g. http://localhost:8080

// Pool state straight from the indexer; falls back to RPC on failure.
const pool = await getPool(connection, mint, config, { indexer })

// History is indexer-only — no RPC equivalent.
const recentSwaps = await getSwapHistory({
  indexer,
  poolId: 1,
  since: new Date(Date.now() - 24 * 60 * 60 * 1000),
  limit: 100,
})

Example — Live Event Bus

import { createIndexerBus } from 'deeppoolsdk'

const bus = createIndexerBus('http://localhost:8080')

const offPool = bus.on('pool', (frame) => {
  console.log('new pool', frame.pubkey, 'token', frame.token_mint)
})

const offSwap = bus.on('swap', (frame) => {
  console.log('swap', frame.is_buy ? 'BUY' : 'SELL', frame.amount_in_net, '→', frame.amount_out_net)
})

bus.onConnectionChange((s) => console.log('bus:', s))

// later
offPool(); offSwap(); bus.close()

Outside a browser (SSR, Node tests) createIndexerBus returns a no-op bus.

Key Properties

  • LP locks — creators lock 20%, community LPs lock 7.5%. Permanently held by pool PDA. Pools only get deeper.
  • Self-deepening — 0.25% swap fee compounds into reserves. K only grows.
  • No freeze authority — LP tokens can never be frozen by anyone.
  • Token-2022 native — no WSOL wrapping.
  • Mint extension blocklistTransferHook, PermanentDelegate, InterestBearingConfig, MintCloseAuthority, NonTransferable, DefaultAccountState, and Pausable mints are rejected at pool creation. TransferFeeConfig and metadata/group extensions are fully supported.
  • Native SOL — SOL reserve is pool PDA lamports, not a token account.
  • Immutable pools — no admin, no fee switch, no close.
  • No protocol fee — 0% extraction. All fees stay in the pool.
  • Formally verified — 21 Kani proofs + 24 proptest properties cover swap math, LP math, K invariant, LP locks, and overflow handling.

Constants

| Parameter | Value | |-----------|-------| | Swap fee | 0.25% (25 bps) | | Creator LP lock | 20% (2000 bps) | | Provider LP lock | 7.5% (750 bps) | | Protocol fee | 0% | | Min initial SOL | 0.1 SOL | | Min initial tokens | 1 token (6 decimals) | | MIN_LIQUIDITY | 1000 (locked on first deposit) | | LP decimals | 6 | | POOL_ACCOUNT_SIZE | 153 bytes |

Re-exports: LAMPORTS_PER_SOL, TOKEN_2022_PROGRAM_ID, PROGRAM_ID, SWAP_FEE_BPS, FEE_DENOMINATOR, POOL_ACCOUNT_SIZE.

Testing

# Mainnet fork (Surfpool) — pure SDK + program path
pnpm test

# Devnet end-to-end against deployed program
pnpm test:devnet

# Local docker stack (program + indexer + db)
docker compose --profile full up -d
pnpm test:local

# WebSocket bus against the local indexer
pnpm test:bus

The local and bus suites need INDEXER_URL (default http://localhost:8080) and a funded keypair at KEYPAIR_PATH.

Links

License

MIT