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

@hammerock/cca-sdk

v0.2.0

Published

TypeScript SDK for Uniswap Continuous Clearing Auctions (CCA): discovery across every factory version, live state, Q96 math and bid construction. Ethereum, Base, Unichain, Arbitrum and their testnets.

Readme

@hammerock/cca-sdk

TypeScript SDK for Uniswap Continuous Clearing Auctions (CCA), built on viem.

It handles auction discovery, live state, Q96 price math, token metadata, and building submitBid transactions correctly. That last part covers the parts of the protocol that are easy to get wrong: ERC-20 bids go through Permit2, and bid prices must sit on a tick boundary.

Networks. Ethereum (1), Base (8453), Unichain (130) and Arbitrum One (42161), plus Sepolia (11155111), Base Sepolia (84532) and Unichain Sepolia (1301). Reading is allowed everywhere; the SDK never signs. Use isTestnet(chainId) to gate anything that spends. Discovery covers every CCA factory version (v2.1.0, v2.0.0 and the deprecated v1.1.0), and token names and symbols are sanitised - they are attacker-controlled on-chain strings.

Built against the ContinuousClearingAuctionFactory v1.1.0 at 0xCCccCcCAE7503Cac057829BF2811De42E16e0bD5. The ABIs are compiled from upstream tag v1.1.0, not hand-written.

Install

npm install @hammerock/cca-sdk viem

viem is a peer dependency, so your app and the SDK share one copy.

Read an auction

import { createBeaconClient, getAuctionSummary, formatTokenAmount } from "@hammerock/cca-sdk";

const client = createBeaconClient({
  rpcUrl: "https://ethereum-sepolia-rpc.publicnode.com",
  chainId: 11155111,
});

const summary = await getAuctionSummary(client, "0x1e40451D6ecabA8640559b7dFbe63B41dA52460d");

console.log(summary.status);           // "pending" | "live" | "ended"
console.log(summary.clearingPrice);    // human-readable price
console.log(summary.state.isGraduated);
console.log(summary.secondsRemaining);

No lens deployment needed. Uniswap publishes no CCALens address. getAuctionState runs AuctionStateLens inside a single eth_call using a state override, so it works against any standard RPC. If you have deployed a lens yourself, pass lensAddress to createBeaconClient.

Discover auctions

import { scanAuctions, watchAuctions } from "@hammerock/cca-sdk";

const auctions = await scanAuctions(client);            // every AuctionCreated since the factory deployed
const stop = watchAuctions(client, (a) => console.log("new auction", a.auction));

eth_getLogs is always chunked (50,000 blocks by default), halves the chunk size when a provider rejects a range, and re-queries empty chunks. Some public RPCs silently return an empty result for a range that has logs. Alchemy's free tier caps eth_getLogs at 10 blocks, so pass a separate logsRpcUrl for scanning.

Place a bid

import {
  buildBidTransactions,
  checkBidReadiness,
  decimalToQ96,
  getAuctionInfo,
  getPrevTickHint,
} from "@hammerock/cca-sdk";

const info = await getAuctionInfo(client, auction);
const maxPriceQ96 = decimalToQ96("0.00000000000000000006");
const amount = 1_000_000_000_000_000n; // in the currency's smallest unit

const readiness = await checkBidReadiness(client, {
  auction,
  currency: info.currency,
  bidder,
  amount,
});

const steps = buildBidTransactions({
  auction,
  currency: info.currency,
  maxPriceQ96,
  amount,
  owner: bidder,
  readiness,
  prevTickPriceQ96: await getPrevTickHint(client, auction, maxPriceQ96),
  tickSpacing: info.tickSpacing,
});

for (const { label, request } of steps) {
  // Send each with your own wallet client, waiting for approvals to land first.
  await walletClient.sendTransaction({ ...request, account, chain });
}

buildBidTransactions returns only the steps that are actually needed:

| Currency | Transactions | | --- | --- | | Native ETH | submitBid with value equal to the amount | | ERC-20 | approve(Permit2) → Permit2.approve(token, auction) → submitBid with value 0, skipping any approval already in place |

Things it handles for you, each of which reverts on-chain if done wrong:

  • ERC-20 bids go through Permit2. The auction pulls funds with Permit2's transferFrom, so approving the auction directly does nothing.
  • Bid prices must be a multiple of tickSpacing, or submitBid reverts with TickPriceNotAtBoundary(). Prices are snapped down, so a bidder's ceiling never rises.
  • Native bids must send msg.value == amount exactly, and ERC-20 bids must send no value.

The SDK never signs or broadcasts anything. You send the returned requests with your own wallet.

Settle bids (exit and claim)

Nothing in a CCA pays out automatically. planSettlement decides what each bid needs and encodes the transactions, including the checkpoint hints exitPartiallyFilledBid requires. Anyone may send them; funds always go to the bid owner. Simulate before sending.

import {
  findBidIds,
  getAuctionInfo,
  getAuctionState,
  planSettlement,
  readSettleState,
} from "@hammerock/cca-sdk";

const info = await getAuctionInfo(client, auction);
const live = await getAuctionState(client, auction);
const state = await readSettleState(client, auction, {
  clearingPriceQ96: live.checkpoint.clearingPriceQ96,
  graduated: live.isGraduated,
  endBlock: info.endBlock,
});

const ids = await findBidIds(client, auction, owner); // reads bids directly - no logs needed
const plan = await planSettlement(client, auction, owner, ids, state);

for (const tx of plan.exits) {
  await client.publicClient.call({ to: tx.to, data: tx.data, account }); // simulate
  // ...then send tx.to / tx.data with your wallet
}
// After the exits land, plan again: freshly exited bids then appear in plan.claim.

The decision logic is pure and exported too: decideBidAction and computeExitHints take plain data, so you can test or reuse them without a chain.

Q96 prices

CCA prices are Q96 fixed-point numbers (value × 2⁹⁶).

import { decimalToQ96, q96ToDecimalString, formatQ96, formatQ96Compact } from "@hammerock/cca-sdk";

decimalToQ96("0.0001");          // truncates DOWN - safe for price caps
q96ToDecimalString(value, 18);   // exact, truncating
formatQ96(value);                // rounded for display
formatQ96Compact(value);         // "5.42118e-20" for very small prices

cumulativeMps tracks how much of the supply schedule has been released. It is not the amount sold: an auction that closes with no bids still reaches 100%. Use totalCleared and currencyRaised for what actually sold.

Node-only helpers

Anything that touches the filesystem is in a separate entry point, so the main entry stays safe for browser bundles:

import { JsonAuctionStore, syncAuctions, enrichStore } from "@hammerock/cca-sdk/node";

API overview

| Area | Exports | | --- | --- | | Client | createBeaconClient, assertSupportedChain, assertChainMatches | | Read | getAuctionState, getAuctionInfo, getAuctionSummary, getAuctionSummaries, getAuctionListStates, getClearingPrice, isGraduated, deriveStatus | | Discover | scanAuctions, watchAuctions, scanAuctionsForToken, auctionCreatedEvent | | Write | buildBidTransactions, encodeSubmitBid, checkBidReadiness, getPrevTickHint, alignPriceToTickBoundary, describeBidBlocker, encodeApproveErc20ToPermit2, encodeApprovePermit2 | | Tokens | getTokenMetadata, formatTokenAmount | | Q96 | decimalToQ96, q96ToDecimalString, q96ToNumber, formatQ96, formatQ96Compact, mpsToFraction | | Auction config | encodeAuctionParameters, decodeAuctionParameters, buildAuctionSteps, validateAuctionParameters | | ABIs | auctionAbi, factoryAbi, auctionStateLensAbi, UPSTREAM_TAG, UPSTREAM_COMMIT | | Constants | FACTORY_ADDRESS, PERMIT2_ADDRESS, NATIVE_CURRENCY, SUPPORTED_CHAINS |

Full source, tests and the apps built on this SDK: github.com/Shubham-Singh-Shoora/Beacon-.

License

MIT