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

@mr-zwets/cauldron-swap-sdk

v0.1.6

Published

TypeScript SDK for trading on the Cauldron DEX on Bitcoin Cash, built with the CashScript SDK

Readme

Cauldron Swap SDK

TypeScript SDK for trading on the Cauldron DEX on Bitcoin Cash, built with the CashScript SDK.

Overview

prepareBuyTokens and prepareSellTokens accept an array of pools and optimally split the trade across them using binary search on the marginal rate of the constant product curve, so each pool ends up at the same marginal cost — minimizing total price impact. Pools that don't save enough to justify their extra transaction bytes are automatically dropped. See multi-pool.md for details on the algorithm.

Note: Pools are fetched from the Cauldron indexer API, which is a trusted third party. All token amounts are in base units (raw on-chain amounts, bigint) — BCMR decimal places are not supported.

Install

Install the cauldron-swap-sdk from NPM with:

pnpm install @mr-zwets/cauldron-swap-sdk

Buy Tokens

import { getCauldronPools, prepareBuyTokens } from "@mr-zwets/cauldron-swap-sdk"
import { userTokenAddress, signer } from "./config"

const furuTokenId = "d9ab24ed15a7846cc3d9e004aa5cb976860f13dac1ead05784ee4f4622af96ea"
const amountToBuy = 100_000n

const cauldronPools = await getCauldronPools(furuTokenId)

// pass all pools — the SDK optimally splits the trade across pools
const { transactionBuilder, totalSatsCost, totalFees, effectivePricePerToken } = await prepareBuyTokens(
  cauldronPools,
  amountToBuy,
  userTokenAddress,
  signer
)

// review the effective price before broadcasting
console.log(`Cost: ${totalSatsCost} sats (${totalFees} fees), ${effectivePricePerToken} sats/token`)

const txDetails = await transactionBuilder.send()

Sell Tokens

import { getCauldronPools, prepareSellTokens } from "@mr-zwets/cauldron-swap-sdk"
import { userTokenAddress, signer } from "./config"

const furuTokenId = "d9ab24ed15a7846cc3d9e004aa5cb976860f13dac1ead05784ee4f4622af96ea"
const amountToSell = 100_000n

const cauldronPools = await getCauldronPools(furuTokenId)

// pass all pools — the SDK optimally splits the trade across pools
const { transactionBuilder, totalSatsReceived, totalFees, effectivePricePerToken } = await prepareSellTokens(
  cauldronPools,
  amountToSell,
  userTokenAddress,
  signer
)

// review the effective price before broadcasting
console.log(`Receive: ${totalSatsReceived} sats (${totalFees} fees), ${effectivePricePerToken} sats/token`)

const txDetails = await transactionBuilder.send()

Rate-Targeted Trading

Two helpers let you query how much liquidity is available at a given price — useful for limit-order-style UIs:

import { getCauldronPools } from "@mr-zwets/cauldron-swap-sdk"
import { computeBuyAmountBelowRate, computeSellAmountAboveRate } from "@mr-zwets/cauldron-swap-sdk"

const cauldronPools = await getCauldronPools(furuTokenId)

// How many tokens can I buy before the marginal rate exceeds 150 sats/token?
const buyableAmount = computeBuyAmountBelowRate(cauldronPools, 150n)

// How many tokens can I sell before the marginal rate drops below 80 sats/token?
const sellableAmount = computeSellAmountAboveRate(cauldronPools, 80n)

// Then feed the result into the existing prepare functions
const result = await prepareBuyTokens(cauldronPools, buyableAmount, userTokenAddress, signer)

Create Pool

import { prepareCreatePool } from "@mr-zwets/cauldron-swap-sdk"
import { signer } from "./config"

const furuTokenId = "d9ab24ed15a7846cc3d9e004aa5cb976860f13dac1ead05784ee4f4622af96ea"
const satsAmount = 100_000n    // BCH liquidity to seed the pool with
const tokenAmount = 100n       // token base units to seed the pool with

// the signer's token address is derived automatically
const { transactionBuilder, poolContractAddress, ownerPkh } = await prepareCreatePool(
  furuTokenId,
  satsAmount,
  tokenAmount,
  signer,
)

console.log(`Pool contract: ${poolContractAddress}`)

const txDetails = await transactionBuilder.send()

The transaction includes an OP_RETURN SUMMON <PKH> output so the Cauldron indexer picks up the new pool immediately.

Withdraw Liquidity

import { getCauldronPools, prepareWithdrawAll } from "@mr-zwets/cauldron-swap-sdk"
import { userTokenAddress, signer } from "./config"

const furuTokenId = "d9ab24ed15a7846cc3d9e004aa5cb976860f13dac1ead05784ee4f4622af96ea"
const poolOwnerAddress = "bitcoincash:qps99uejnueu4dsv0dd2m9u9uzxntg66nyux08wmzq"
const cauldronPools = await getCauldronPools(furuTokenId)

// filter your pool
const poolToUse = cauldronPools.find(pool => pool.owner_p2pkh_addr == poolOwnerAddress)

// prepare withdraw transaction
const { transactionBuilder } = await prepareWithdrawAll(
  poolToUse,
  userTokenAddress,
  signer,
)

const txDetails = await transactionBuilder.send()

Chipnet Usage

import { ElectrumNetworkProvider } from 'cashscript';
import { getCauldronPools, prepareBuyTokens } from "@mr-zwets/cauldron-swap-sdk"
import { userTokenAddress, signer } from "./config"

const chipnetTokenId = "53636bc8c1afbe35a7ba169eadfac0aebadeacf96954a9a066a483e885580ed4"
const amountToBuy = 100n

// fetch pools from chipnet indexer
const cauldronPools = await getCauldronPools(chipnetTokenId, 'chipnet')

// use a chipnet provider for the transaction
const provider = new ElectrumNetworkProvider('chipnet')
const { transactionBuilder } = await prepareBuyTokens(
  cauldronPools,
  amountToBuy,
  userTokenAddress,
  signer,
  provider
)

const txDetails = await transactionBuilder.send()

Custom Arifacts

The Cauldron contract does not have a ready-to-go CashScript artifact, so custom artifacts were created to be able to use the CashScript SDK tooling.

You can see the JSON artifacts in src/artifact and find an explanation of this in artifacts.md

Run the Tests

npm i
npm run test

or using pnpm:

pnpm i
pnpm run test

Future Extensions

BCMR token metadata

The trading logic currently operates on base token units (the raw on-chain amount). The BCMR standard allows tokens to define a ticker symbol and decimal places for a higher-level display unit, but this SDK does not yet support that abstraction. Token amounts passed to prepareBuyTokens/prepareSellTokens must be in base units (and hence are BigInt type).

On-chain pool discovery

Currently pool discovery relies on the Cauldron indexer API, which is a trusted third party. Ideally pools could be discovered directly on-chain. The challenge is that Cauldron pools use P2SH, so the contract code is hidden behind a hash — you can't identify them by script fingerprinting alone. However, new pools can be discovered by their OP_RETURN marker SUMMON in the creation transaction. BCHN's bytecode pattern RPC (redeemBytecodePattern with fingerprint matching) could help identify existing pools when they are spent, since the redeem script is revealed at spend time.