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

hunch-cup

v0.5.3

Published

One-line CLI + typed SDK to paper-trade the Hunch Cup tournament: claim 10,000 $pUSDC, trade live markets with zero real-funds risk, run momentum/contrarian/news-reactive agents, and climb the public leaderboard.

Readme

hunch-cup

One-line CLI + typed SDK to play the Hunch Cup — a risk-free, paper-trading prediction-market tournament. Claim 10,000 $pUSDC (paper money, zero real-funds risk), trade the live Hunch catalog, run a 24/7 agent, and climb a public leaderboard scored on realized PnL. The top 50 wallets split a real $5,000.

Everything here is paper. $pUSDC never touches a chain and is never redeemable. The only real money is the prize, paid to the top-50 wallet addresses at the end.

CLI

# 1. Generate a wallet, claim 10,000 $pUSDC, and enroll as a self-operated agent
#    (prints a private key — save it!)
#    Always use @latest: npx reuses the first version it cached, and CLIs older
#    than 0.5.0 can't enroll — they hit a bare `cup_agent_trades_halted` on trade.
npx hunch-cup@latest wallet new

export HUNCH_CUP_PRIVATE_KEY=0x...   # the key it printed (Windows: use `set` / `$env:`)

# Already have a wallet? Enroll it once so live trading stays open for you
# even while our own bot fleets are halted. Idempotent.
npx hunch-cup@latest enroll

# 2. Look around
npx hunch-cup markets
npx hunch-cup quote <slug> yes 25

# 3. Trade (a REAL paper trade is signed automatically by your key)
npx hunch-cup trade <slug> yes 25

# Binary markets take `yes`/`no` (up/down markets accept `yes`/`no` too).
# Multi-outcome markets (mcap/price ladders, token races, head-to-heads) take an
# OUTCOME KEY as the side — e.g. a ladder bucket key like `63m-67m`, or a token
# candidate key like `zec`. Recurring markets trade on their current round.

# 4. Or let an agent do it — momentum | contrarian | news-reactive
npx hunch-cup run momentum 25            # dry-run (simulated)
npx hunch-cup run contrarian 25 --live   # one round, actually place trades

# 24×7, built in — no shell loop needed. It reads your balance first, skips
# markets you already hold, caps each round to a fraction of your bankroll, and
# stops before it goes broke (the old `while true` loop went insolvent in ~20m).
npx hunch-cup run momentum 25 --live --loop --interval 300

npx hunch-cup positions   # balance + open/realized positions (watch for insolvency)
npx hunch-cup balance     # just the $pUSDC number
npx hunch-cup board

# 5. Roulette — a separate paper surface: every spin settles 42 parimutuel
# markets (colour/dozen/half/parity/column + 37 per-number HITS/MISSES). No house
# odds — winners split the whole market pool; the edge is betting where the crowd
# % misprices the wheel's true k/37 %.
npx hunch-cup roulette                    # the live round + all 42 markets + betKeys
npx hunch-cup roulette-quote colour:red 25  # dry-run: crowd % vs true %, est pay-if-win
npx hunch-cup roulette-bet num:17:yes 25    # a REAL signed bet on the live spin

Run a fleet (one person, many agents)

npx hunch-cup fleet new 10        # mint 10 wallets, claim each, save to ~/.hunch-cup/fleet.json
npx hunch-cup fleet run momentum  # run all 10 concurrently, 24×7 (each with a strategy)
npx hunch-cup fleet board         # every wallet's live rank

fleet new assigns a rotating strategy (momentum / contrarian / news-reactive) per wallet so a demo fleet is visibly diverse. Keys live only in the local file.

Env: HUNCH_CUP_PRIVATE_KEY, HUNCH_CUP_BASE_URL (default https://www.playhunch.xyz), HUNCH_CUP_SIZE (default 25), HUNCH_CUP_SENTIMENT (for news-reactive), HUNCH_CUP_FLEET_FILE (default ~/.hunch-cup/fleet.json).

SDK

import { CupClient, fromPrivateKey } from "hunch-cup";

const client = new CupClient({ signer: fromPrivateKey(process.env.HUNCH_CUP_PRIVATE_KEY!) });

await client.createWallet();                       // claim 10,000 $pUSDC (once)
const markets = await client.listMarkets(25, 0);   // paginated: limit, offset
await client.simulateTrade(markets[0].slug, "yes", 25);   // dry run, no signature
await client.trade({ slug: markets[0].slug, side: "yes", sizePhunch: 25 }); // signed
await client.getWallet();                          // balance + positions (typed)
await client.getLeaderboard({ wallet: client.address });

// Roulette (42 parimutuel markets per spin, no house odds):
const round = await client.getRouletteRound();     // live round + all 42 markets + betKeys
await client.simulateRouletteBet("colour:red", 25);              // dry run, no signature
await client.rouletteBet({ betKey: "num:17:yes", stakePhunch: 25 }); // signed, live spin

// Built-in strategy templates (pure deciders, you control execution). N-way
// markets (ladders, THE FLIP) pick a real outcome key, never phantom yes/no.
await client.runStrategy({ strategy: "momentum", sizePhunch: 25, live: true });

// Bankroll-managed 24×7 loop (survives insolvency + transient errors):
await client.runLoop({ strategy: "momentum", sizePhunch: 25, intervalMs: 300_000, live: true });

// A whole fleet from one process:
import { fleetNew, fleetRun } from "hunch-cup";
await fleetNew(10);
await fleetRun({ defaultStrategy: "momentum", sizePhunch: 25, intervalMs: 300_000 });

How auth works

Reads are public. A real paper trade is proven with an EIP-191 signature over a canonical message binding { wallet, market, side, size, tradeId, issuedAt } — so only a wallet's owner can spend its $pUSDC. The SDK/CLI signs for you. A simulate trade writes nothing and needs no signature.

Errors

Every non-2xx response throws a typed CupApiError carrying status, code, the server's hint, and retryable. Anything the server marks retryable: false is a refusal, not a blip — runLoop and fleetRun stop on one instead of re-firing it every interval.

cup_agent_trades_halted (503) — and how enrollment clears it

We run house and prize bot fleets of our own. When those have to be stopped, the switch is server-side — and nothing in the data separates a fleet wallet from yours (both are keyless agent wallets, no login). So the carve-out is something you do, not something we guess:

npx hunch-cup@latest enroll "momentum bot, @me"    # one signed call, idempotent

That declares the wallet a self-operated agent and reopens live trading for it immediately — no ticket, no waiting, while the fleets stay stopped. You normally never have to run it: hunch-cup wallet new enrolls on creation, and a live trade that gets refused enrolls once and retries the same tradeId (so the retry can't double-spend).

const client = new CupClient({ signer });              // autoEnroll: true by default
await client.trade({ slug, side, sizePhunch: 25 });    // enrolls + retries if halted

new CupClient({ signer, autoEnroll: false });          // or handle it yourself:
try {
  await client.trade({ slug, side, sizePhunch: 25 });
} catch (err) {
  if (isCupHaltError(err)) { await client.enroll(); /* retry */ }
  else throw err;
}

Enrollment signs a domain-separated statement, so you can only enroll a wallet you hold the key for. House-registered fleet wallets are refused (403 house_fleet_wallet).

If you're seeing the refusal anyway, reads and dry runs never stop working:

hunch-cup run momentum 25          # dry run — same picks, full pricing, no write
hunch-cup markets                  # the live paper catalogue
hunch-cup quote <slug> yes 25      # live pool-implied odds
hunch-cup board                    # the leaderboard

Balances and positions are untouched; the halt freezes writes, it doesn't unwind anything. run --live prints the explanation, shows the round it would have traded, and exits 75 (EX_TEMPFAIL) so a supervisor knows not to restart it hot. GET /api/cup/v1/getting-started advertises all of this up front (tradingHalted), so an agent can check before it ever signs.

MCP

There's also a remote MCP server at https://www.playhunch.xyz/api/cup/mcp (create_wallet, list_markets, get_quote, place_paper_trade, get_roulette_round, place_roulette_bet, get_positions, get_leaderboard, getting_started). place_paper_trade and place_roulette_bet both default to simulate.

License

MIT