
Crypto bounties, puzzles and challenges data library
Public crypto puzzles and bounties, as typed records. You ask for a puzzle, you get its address, its key material and what happened on chain.
Every puzzle thread has the same three things: the addresses, the prizes, and who solved what. Every scanner and tracker re-types them from the thread, slightly differently each time. So they live here once, as code. A puzzle is a TypeScript record. The type checker reads it before a test does. The CLI, the MCP server and the Pi and OMP extensions read one registry.
Docs, one page per puzzle and a live playground: puzzles.agntn.dev.
[!WARNING] Pre-1.0. The API, the CLI flags and the data model can still move. Pin an exact version if you build on it.
PuzzleSpec literal per puzzle, built by one puzzle() factory for every chain. No JSON, no build step.get("bits/71") imports one collection module.puzzle.balance() through @agntn/explorers. Base units as bigint, API keys redacted from errors.puzzles watch lists the deposits and spends a record misses, a prize that moved, a public key a spend gave away, a source page that changed. It never edits a record. You do.puzzles eligibility gathers the source, the address, lifetime totals from the explorer, the status with its evidence and what counts as a solution. Whatever nobody can fill comes back as a missing row, never a guess.puzzles_assets hands a model the image, the stage files and the archived posts behind the hints, checked against the SHA-256 the record pins. Links rot. These don't.pnpm add @agntn/puzzles
Node.js 26 or newer for the CLI.
npx @agntn/puzzles stats
That prints the total, one count per status and how many puzzles have a known public key. No key, no config, no network. The records ship inside the package. The bare puzzles below is pnpm exec puzzles after a local pnpm add, or just puzzles after pnpm add -g @agntn/puzzles.
puzzles show hash-collision/sha256
hash-collision/sha256 unsolved 0.27734251 BTC 35Snmmy3uhaer2gTboc81ayCip4m9DT4ko
chain: bitcoin address kind: p2sh
hash160: 292fb39df7cd619a396069383928e6bfb74ebec5
redeem script: 6e879169a87ca887 (hash 292fb39df7cd619a396069383928e6bfb74ebec5)
public key: unknown
private key: unknown
started: 2013-09-13 05:59:09
transactions: 1
funding 2013-09-13 05:59:09 0.1 BTC 397f12ee15f8a3d2ab25c0f6bb7d3c64d2038ca056af10dd8251b98ae0f076b0
explorer: https://blockstream.info/address/35Snmmy3uhaer2gTboc81ayCip4m9DT4ko
source: https://bitcointalk.org/index.php?topic=293382.0
| Command | What it prints |
|---|---|
puzzles stats | Totals, status counts, prize sums and the data version |
puzzles collections | One row per collection: key, counts, author |
puzzles authors [key] | One row per author, or one author's record with its sourced facts |
puzzles author <key> | One author's record, straight from the puzzles_author tool |
puzzles solvers [key] | One row per named solver, or one solver's record: every solve, profiles and sourced facts |
puzzles solver <key> | One solver's record, straight from the puzzles_solver tool |
puzzles show <id> | One puzzle's record: key material, transactions, hints and links. --json for the data |
puzzles hints <id> | The collection's hints, the puzzle's own, then its hint files. --json for both |
puzzles stages <id> | The stages of a multi-stage puzzle with their pages, files and published answers. --json for the list |
puzzles assets <id> | The files a puzzle ships with SHA-256 and size, and the archived pages it cites. --read <path> writes one, --check/--live verify |
puzzles list [collection] | One puzzle per line. --address, --chain, --status, --technique and --with-pubkey narrow it, --limit and --offset page it |
puzzles verify [id] | A published key and its recipe against the address. --all or the list filters for a set, exit 1 on a mismatch |
puzzles balance [id] | The live balance. The list filters check a whole set, one row each. --api-key, or one variable per chain |
puzzles watch [id] | What the chain knows and the record doesn't. --since checks the source pages too, exit 1 on any finding |
puzzles eligibility <query> | The checklist before working on a prize, by id or address. Exit 1 while any field is missing |
puzzles export | The whole dataset with its data_version |
puzzles mcp | The MCP server over stdio |
--json prints the data behind the text, bigint as strings and absent fields left out. The commands come from the same tool definitions the agents get, so a typo in a flag fails here just like it fails for a model. The flags and exit codes are in the CLI guide.
import { get, stats, verify } from "@agntn/puzzles";
import { bits } from "@agntn/puzzles/collections/bits";
const puzzle = await get("bits/71"); // loads the bits collection, nothing else
puzzle?.address().value; // "1PWo3JeB9jrGwfHDNpdGK54CRas7fsVzXU"
puzzle?.keyRange(); // [2n ** 70n, 2n ** 71n - 1n]