@agntn/puzzles
v0.27.1
Published
Crypto bounties, puzzles and challenges as class-owned data for agents
Maintainers
Readme
@agntn/puzzles
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.
Why?
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.
✨ Features
- 🧾 Data as code. One
PuzzleSpecliteral per puzzle, built by onepuzzle()factory for every chain. No JSON, no build step. - 🕳️ Absent means absent. A puzzle without a solver or a prize has no such key. Nothing serializes as null.
- 🔑 Key material in every shape. Hex, WIF, a BIP38 payload, a seed phrase, secret shares, or just a bit width. One builder.
- 💤 Lazy registry. Importing the package loads no records.
get("b1000/71")imports one collection module. - ✅ Verification is a value. A published key derives the address or it doesn't. Nothing throws for a bad record.
- 💰 Live balances.
puzzle.balance()through@agntn/explorers. Base units asbigint, API keys redacted from errors. - 👀 A watch on the record.
puzzles watchlists the deposits and spends a record misses, a prize that moved, a source page that changed. It never edits a record. You do. - 📋 A checklist before the weekend.
puzzles eligibilitygathers 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 amissingrow, never a guess. - 🤖 Fourteen agent tools. One executor behind MCP, Pi and OMP. Same answer everywhere.
- 🌐 Runs anywhere. Neutral ESM on the Fetch API. Node, browsers, edge workers.
📦 Install
pnpm add @agntn/puzzlesNode.js 26 or newer for the CLI.
🚀 First call
npx @agntn/puzzles statsThat 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/sha256hash-collision/sha256 unsolved 0.277343 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.0Commands
| Command | What it prints |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| puzzles stats | Totals and status counts. --json adds the prize sums |
| 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 solvers [key] | One row per named solver, or one solver's record: every solve, profiles and sourced facts |
| 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. --check <dir> hashes your copies, --live the author's URLs |
| puzzles list [collection] | One puzzle per line. --address, --chain, --status and --with-pubkey narrow it, --limit and --offset page it |
| puzzles verify [id] | A published key against its address. --all for every puzzle, 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 is the same serializer everywhere, bigint as strings and absent fields left out. The flags and exit codes are in the CLI guide.
🧠 Library
import { get, stats, verify } from "@agntn/puzzles";
import { b1000 } from "@agntn/puzzles/collections/b1000";
const puzzle = await get("b1000/71"); // loads the b1000 collection, nothing else
puzzle?.address().value; // "1PWo3JeB9jrGwfHDNpdGK54CRas7fsVzXU"
puzzle?.keyRange(); // [2n ** 70n, 2n ** 71n - 1n]
(await verify(b1000.require(1))).verified; // true, key 1 derives its address
(await stats()).unsolved; // how many are still waiting for a key
(await b1000.require(71).balance()).totalUnits(); // 7.10190014 when I ran it, mempool.space decidesThat's most of it, really. A collection is its own entry and everything on it is synchronous. The views that span collections await a load. Errors descend from PuzzlesError, balances have their own family under BalanceError. The rest is in the guides: records, registry, lookups, verification, balances.
🗺️ Collections
| Key | Chains | What it is |
| ----------------------- | ----------------------------------- | ------------------------------------------- |
| b1000 | bitcoin | Keys of 1 to 256 bits, one address each |
| quizchain | bitcoin | Quiz blocks chained by their keys |
| quizchain2 | bitcoin | Quizchain's second run, from May 2019 |
| rushwallet | bitcoin | Brainwallets from a 2014 contest |
| zden | bitcoin, ethereum, litecoin, decred | Zden's visual puzzles |
| arweave | arweave, ethereum | Tiamat's weave puzzles |
| mini | bitcoin, bitcoincash | RetiredCoder's seven mini-puzzles |
| warp | bitcoin | Keybase's scrypt brainwallet challenges |
| hash-collision | bitcoin | Peter Todd's P2SH collision bounties |
| teikhos | ethereum | Contracts that pay for a public key |
| ballet | bitcoin | BIP38 keys printed on physical wallets |
| dug | bitcoin | 2025 student seed hunt |
| bitimage | bitcoin | Seeds hashed from photographs |
| luckylurker | bitcoin | Two Bitcoin Vault seed challenges |
| iamabananaamaa | bitcoin | A ZIP in a GIF, then a fake Caesar |
| doges-gambit | ethereum, dogecoin | Two keys read off one chess board video |
| bitaps | bitcoin | A 3 of 5 secret sharing scheme |
| gsmg | bitcoin | A multi phase image puzzle |
| movie-enigma | bitcoin | Film titles as seed words, solved 2026 |
| ledger-donjon | bitcoin | Scissors Secret Sharing from the CTF |
| coin-artist | bitcoin | TORCHED H34R7S painting |
| genesis | bitcoin | Genesis block OP_RETURN puzzle |
| mineshop | ethereum | A seed split between a video and a post |
| satoshi-birthday-quiz | bitcoin | Seven quiz answers hashed into a wallet |
| book-quiz | bitcoin | A book quiz nobody won in time |
| 80-bit | bitcoin | 80 hidden bits and a mempool race |
| wickex | bitcoin | Hex, Morse and a spectrogram passphrase |
| picture-puzzle | bitcoin | Four pictures that spell a key database |
| brave-new-world | bitcoin | A seed phrase hidden in a 2020 collage |
| wealth-in-poetry | bitcoin | Seed words hidden in a 2019 Medium essay |
| path-to-greatness | litecoin | Clues from a game demo, a Litecoin key |
| proof-of-writing | ecash | A Cashtab seed on an essay's diagonal |
| bitaddress | bitcoin | A BIP38 wallet with a forgotten passphrase |
| powerful-moss | base | A seed in an album, the prize in a contract |
| trivia-brainwallet | bitcoin | Twelve trivia riddles salted into scrypt |
| great-riddle | bitcoin | Seed words hidden in ballpoint pen drawings |
Identifiers are collection/name. A singleton, such as gsmg, genesis or 80-bit, is just the key. Each collection has a page with the story, the quirks and every puzzle: puzzles.agntn.dev/collections.
🤖 Agents
claude mcp add puzzles --scope user -- npx -y @agntn/puzzles mcp
claude mcp add --transport http puzzles https://puzzles.agntn.dev/mcp # nothing to install
pi install npm:@agntn/puzzles{
"mcpServers": {
"puzzles": { "command": "npx", "args": ["-y", "@agntn/puzzles", "mcp"] }
}
}Fourteen tools: puzzles_stats, puzzles_collections, puzzles_authors, puzzles_author, puzzles_solvers, puzzles_solver, puzzles_show, puzzles_hints, puzzles_stages, puzzles_list, puzzles_verify, puzzles_balance, puzzles_watch and puzzles_eligibility. The last three leave the process, and their annotations say so. What the text carries and where the limits live: the agents guide.
🚫 What this does not do
It doesn't solve anything. No scanner, no kangaroo, no brainwallet cracker, and no guessing a status from a transaction list. solved, swept, claimed and expired are written down by hand, because a claim transaction plus a published key still means solved. Chain facts come from @agntn/chains, key derivation from @agntn/keys and balances from @agntn/explorers. This package doesn't reimplement any of them.
🧩 Adding a puzzle
One record file under src/collections/<key>/ and one line in the collection module. Then pnpm test runs the data gate: unique ids, address and txid formats, key derivation, BIP38 payloads, asset paths and their SHA-256, no nulls. The shape of a record is in Puzzle records and the rules in CONTRIBUTING.md.
🛠️ Development
pnpm install
pnpm --dir docs install # the docs site; lint and test read the Nuxt types it generates
pnpm lint # vp lint and vp fmt, docs included
pnpm typecheck # builds first, then checks src, Pi and OMP
pnpm test # unit tests and the data gate
pnpm test:packed # packs the tarball and runs every published entry without src/
pnpm docs # the Docus site on localhost💛 Thanks
This package exists thanks to the open source programs at Anthropic and OpenAI: Claude for Open Source and Codex for Open Source.
