STATUS · Built and tested locally. Not a public network. No public node. Mainnet anchoring waits on a funded key. First Mints and the art certificates are previews or rehearsals.
CHAIN · DEV TOOLS · SOURCE da7bc09 · LOCAL TODAY
Run the chain on your machine.
Everything here runs on a laptop. The repo is local today and has no public remote, so there is no clone URL on this page; the steps assume you have a copy. Dev chains use public keys, so nothing on one has value.
quickstarthttp apimcpclisdkdocsverify deskproof of balanceart mirror
01 · QUICKSTART · RUST VIA RUSTUP
Five steps to a running town.
1 · Install Rust (stable), if you don’t have it
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal 2 · Run the tests, core first
cargo test -p chain-core
cargo test --workspace
(cd crates/kernel && cargo test) # the rollup kernel is its own workspace 3 · Start a dev chain with synthetic traffic
cargo run -p node -- run --dev --demo --dev uses publicly derivable keys. --demo adds two humans, a tz2 human, two agents (Frog and
Sparrow) and the MCP agent (Wire Desk), then generates taps, posts, drum sessions, drop mints and transfers.
4 · Open what it serves
| Open | What you see |
|---|---|
http://127.0.0.1:8545/ | The explorer. Press ✓ VERIFY and your browser replays the chain. |
/status | Height, tip, state root, supply, chain id and genesis hash. |
/metrics | Prometheus text for the night shift. |
/readyz | 200 while blocks are fresh; 503 when the tip is older than 9 seconds. |
5 · Add Town Hall, following the node from step 3
cargo run -p pointcast-town -- --node http://127.0.0.1:8545
# Town Hall http://127.0.0.1:8550/ (also /hall)
# API http://127.0.0.1:8550/api/town/status
Or, with nothing else running, scripts/town-demo.sh starts its own --dev --demo node and
pc-town on throwaway databases and removes them on Ctrl-C. It refuses to start if something already answers on
8545 or 8550, so stop the step 3 node first. pc-town holds no keys.
Then · let an agent in, and ask the doctor
claude mcp add --transport http pointcast-chain http://127.0.0.1:8545/mcp
claude mcp add --transport http pc-town http://127.0.0.1:8550/mcp
cargo run -p node -- doctor --db data/chain.sqlite # a dev chain is NOT READY, and it says why 02 · HTTP API · 33 ROUTES ON THE NODE · 15 ON PC-TOWN
Every route, from the route declarations.
The node listens on 127.0.0.1:8545 by default and pc-town on 127.0.0.1:8550. Both send permissive CORS. File names are under crates/node/src/ and crates/town/src/.
| Method | Path | Returns | File |
|---|---|---|---|
| GET | / | The explorer: the chain as a PointCast-style feed, with VERIFY and the Transmit wallet panel. | api.rs |
| GET | /status | Height, tip, state root, supply, counts, chain_id and genesis_hash. | api.rs |
| POST | /tx | Submit a SignedTx (JSON) → {tx_hash}. | api.rs |
| POST | /tx/digest | Unsigned tx → the raw digest, plus the wallet message and Micheline payload to sign. | api.rs |
| POST | /drum/digest | Drum session claim → attestation digest and per-player co-sign payloads. Sizes are bounded before the node lock. | api.rs |
| GET | /tx/{hash} | pending · included (with receipt) · rejected (with reason). | api.rs |
| GET | /block/latest | The newest block with tx cards. | api.rs |
| GET | /block/{height} | One block with tx cards. | api.rs |
| GET | /account/{address} | Balance, nonce, next_nonce (counts the mempool), agent info, drops. | api.rs |
| GET | /feed | Newest blocks first. ?limit=20&before=H&all=false; all=true includes empty blocks. | api.rs |
| GET | /anchors | Recent anchor payloads and their status. | api.rs |
| POST | /body | Store a block body off chain (at most 64 KiB) → {body_hash}. | api.rs |
| GET | /body/{hash} | Body text. | api.rs |
| POST | /mcp | The MCP server (JSON-RPC 2.0, streamable HTTP). GET answers 405. | api.rs |
| GET | /metrics | Prometheus text: height, block age, mempool depth, txs and ATTN by kind, supply, accounts at the epoch cap, top-10 issuance share, anchors by status, db bytes. | ops.rs |
| GET | /healthz | ok, unless the node lock is poisoned. | ops.rs |
| GET | /readyz | 503 when the tip is older than PC_READY_MAX_BLOCK_AGE_MS (default 9,000). | ops.rs |
| GET | /params | Genesis params; blake2b(params) is /status.genesis_hash. | api_raw.rs |
| GET | /raw/block/{height} | The exact serde Block, every signature included (404 if missing). | api_raw.rs |
| GET | /raw/blocks | ?from=H&limit=N → {tip, from, blocks}, ascending, N ≤ 500. | api_raw.rs |
| GET | /verifier/pointcast_chain.wasm | The verifier wasm. | api_raw.rs |
| GET | /verifier/pointcast_chain.wasm.sha256 | Its committed sha256. | api_raw.rs |
| GET | /verifier/verify.js | The page-side verifier wrapper. | api_raw.rs |
| GET | /verifier/verify-worker.js | The Web Worker that replays blocks. | api_raw.rs |
| GET | /proof/account/{addr} | An unsigned proof at the tip. | proofs.rs |
| GET | /proof/claim/{addr} | ?height=H → a balance claim at a retained anchor; 404 “replay required” once the snapshot is gone. | proofs.rs |
| GET | /agent/{addr}/mandate | The agent’s mandate as the next block sees it, or 404 {"mandate": null}. | api_mandate.rs |
| GET | /drops | ?prefix&creator&after&limit → drops sorted by id, with creator, minted and remaining. | api_art.rs |
| POST | /drops/prepare-mint | An unsigned drop_mint with advisory checks and the wallet payload. Refuses to create a drop unless create:true. | api_art.rs |
| GET | /drop/{id} | One drop: creator, minted, chain cap, remaining, first height. | api_art.rs |
| GET | /drop/{id}/mints | Mints in chain order. Editions can’t move, so this is the holder list. | api_art.rs |
| GET | /account/{address}/drops | ?at=tip|anchor&height&drop → editions held, with a chain-proof claim. | api_art.rs |
| POST | /tx/simulate | Run a SignedTx through the real apply_tx on a copy of the tip. | api_art.rs |
| Method | Path | Returns | File |
|---|---|---|---|
| GET | / | Town Hall (#/ square, #/a/{addr}, #/c/{code}, #/r/{room}, #/b/{h}). | api.rs |
| GET | /hall | The same page. | api.rs |
| GET | /api/town/health | ok, halted, or a fault with its evidence; 503 when not ok. | api.rs |
| GET | /api/town/status | Verified height, state root, supply, counts, recent state roots. | api.rs |
| GET | /api/town/accounts | The register. | api.rs |
| GET | /api/town/account/{addr} | Balance, the epoch ATTN tank, tap window, agents, mandate, attestations, first page of txs. | api.rs |
| GET | /api/town/account/{addr}/txs | ?before=H&role=R → older txs, with the account’s roles in each. | api.rs |
| GET | /api/town/channels | Channels. | api.rs |
| GET | /api/town/channel/{code} | One channel’s posts. ?before=H | api.rs |
| GET | /api/town/rooms | Rooms. | api.rs |
| GET | /api/town/room/{room} | Sessions, attestation mix, credited-seconds leaderboard this epoch. | api.rs |
| GET | /api/town/blocks | Recent blocks. ?busy=true | api.rs |
| GET | /api/town/block/{h} | A replayed block with its txs and receipts. | api.rs |
| GET | /api/town/body/{hash} | The node’s body, re-hashed; 502 if it doesn’t match body_hash. | api.rs |
| POST | /mcp | Read-only MCP. GET answers 405. | api.rs |
Signatures bind the chain’s genesis hash as well as its id, so take both from GET /status before you sign.
03 · MCP · 6 TOOLS ON THE NODE · 4 ON PC-TOWN
Agents use the same chain.
Write tools take a client-signed signed_tx (preferred: the agent holds its own key) or plain fields that the
node signs as its custodial agent. /mcp has no caller auth, so the custodial path refuses any request that
carries an Origin header.
-
POINTCAST-NODE · mcp.rs
post_blockPublish a PointCast Block on chain. The node stores the body off chain; the chain records its hash.drum_sessionRecord a finished drum session. Players earn capped ATTN only if attested: the sender always, others by co-signature or a room attestation.get_feedNewest blocks first, with transaction cards.my_mandateThe owner-granted mandate bounding an agent: kinds, channels and rooms, allowance left, payees, blocks until expiry.spend_allowancePay ATTN from the agent’s owner’s balance, within the mandate’s caps and payee list. The custodial path refuses browser requests.prove_balanceA portable balance claim: the sealed tip, or a retained anchor at a given height. Verify offline with the genesis params.
-
PC-TOWN · mcp.rs · READ ONLY
town_statusThe town square from pc-town’s own replay, with health.town_accountOne account as pc-town replayed it: balance, epoch tank, tap window, agents, mandate, newest txs.channel_feedA channel’s posts, newest first.room_sessionsA room’s drum sessions, attestation mix and this epoch’s leaderboard.
04 · CLI · POINTCAST-NODE · PC-SIM · PC-TOWN
13 subcommands, and two more tools.
| Command | Usage | What it does |
|---|---|---|
run | run [--dev] [--demo] [--db PATH] [--addr HOST:PORT] [--block-ms N] | Start the sequencer. On restart it replays every stored block and re-checks signatures and roots. |
keygen | keygen [--secp256k1] | A new key, its tz address and its agent address. Store the secret in a secret manager. |
sign | sign --nonce N [--agent | --wallet] --chain ID --genesis HEX '<tx kind JSON>' | Sign a tx with PC_SIGNER_SECRET; --wallet produces what Kukai or Temple return. |
attest-drum | attest-drum --as player|room [--mode raw|wallet] … | Print a drum co-signature or room attestation. |
presence-ticket | presence-ticket --login ID --holder ADDR --room R … | Sign a presence ticket locally, as a reference issuer. |
anchor | anchor status|reveal|post|verify|keygen | Tezos anchoring. Only post --yes signs and spends tez. |
evidence | evidence check <evidence.json> --params <params.json> | evidence params --db PATH | Check sequencer-fault evidence offline. Exit 0 is a proven fault, 1 is not evidence. |
prove | prove <addr> [--height H] [--db PATH] | Export a balance claim (Proof of Balance). |
verify-claim | verify-claim <claim.json> --params <params.json> [--genesis HEX] | Verify a claim offline. Prints PROVEN and exits 0, or exits 1. |
doctor | doctor [--db PATH] [--json] [--allow-dev] | Offline launch checks. Prints PASS, WARN or FAIL lines, then READY or NOT READY (exit 1). |
backup | backup --db SRC --out DST | A consistent snapshot of the database. |
restore | restore --from BACKUP --db DST [--verify] | restore --verify-only BACKUP | Restore, proven by a full replay with --verify. |
art | art mirror|create|setup-dev|house|status|submit|record-fixture | The pointcast-chain side of a 1 tez Tezos art sale. Without --yes nothing is signed. |
-
PC-SIM · THE ECONOMY SIMULATOR
pc-sim run <scenario.json> [--days N] [--seed N] [--out DIR] pc-sim sweep <scenario.json> --grid key=v1,v2 [--grid …] pc-sim bounds [scenario.json]Scenario output, not a forecast. Each run prints seed → root and writes summary.json, days.csv and a self-contained report.html.
-
PC-TOWN · TOWN HALL
pc-town [--node URL] [--genesis HEX] [--db PATH] [--addr HOST:PORT]Follows a node, replays every block with the real verifier, and serves Town Hall.
--genesispins the chain and refuses a node that serves another one.
Scripts: scripts/town-demo.sh, scripts/art-demo.sh, scripts/build-verifier.sh, scripts/pin-verifier.sh. Examples: cargo run -p node --example lying_node and --example proof_demo.
05 · SDK · ONE FILE · ZERO DEPENDENCIES · BROWSER AND NODE 20+
pointcast-chain.js
One ES module that mirrors chain-core byte for byte: the test vectors are generated from Rust, and the Rust side refuses to drift from them. It reads drops and holders, verifies ownership claims locally, and has a Tezos wallet sign through Beacon only after rebuilding the payload itself. It is published here unchanged from the repo.
Download pointcast-chain.js 48 KB · ES module · MIT, per its package.json · from da7bc09
Read · connect, read a drop, check holdings
import * as pcc from "https://pointcast.xyz/chain/sdk/pointcast-chain.js";
// 1. Connect, and pin the chain you expect (from your own config, not the node).
// With no node, connect(null) gives a client whose reads return {status: "no_node"}.
const chain = await pcc.connect("http://127.0.0.1:8545", {
expect: { chainId: "pointcast-dev", genesisHash: GENESIS_HASH },
});
// 2. Read a drop and its holders. Editions can't move, so the mints are the holders.
const drop = await chain.getDrop("coffee-mug-0");
const mints = await chain.getMints("coffee-mug-0");
// 3. Check holdings. The claim is verified in your browser: Merkle path, sequencer seal, pinned genesis.
const h = await chain.getHoldings("tz1…", { drop: "coffee-mug-0" });
h.verification.verifiedHolder; // false on any --dev chain, by design
h.verification.holderReason; // why not Sign · for the creator’s desk
// For the creator's desk, not a public gallery. The creator's Kukai signs.
const tx = await chain.buildDropMint({ sender: creatorTz2, dropId: "coffee-mug-0", recipient: buyer });
const prepared = await chain.digest(tx); // throws unless the node's digest equals the local rebuild
// Kukai shows only kind, sender, nonce and digest: show the creator your own summary of tx first.
const signed = await chain.signWithBeacon(dAppClient, prepared);
await chain.simulate(signed); // optional dry run on the real state machine
const { txHash } = await chain.submit(signed); // throws unless the node reports the local tx id
await chain.waitForTx(txHash);
There is no public node, so a gallery today calls pcc.connect(null) and renders
pcc.certificateCopy("no_node"): “PointCast chain: local rehearsal only. No certificates are issued or promised.”
Only verification.verifiedHolder may earn a badge, and it needs a named drop, a genesis pinned by the caller, a
verified claim and a chain that isn’t a dev chain. In Node, download the file and import it from disk.
Pure exports include blake2b, sha256, addressKind, recipientStatus,
encodeTx, signingHash, walletText, txHash, bodyHash,
paramsHash, checkDropId, verifyClaim, verifyOwnership and
certificateCopy.
06 · DOCS · COPIED FROM THE REPO AT da7bc09
Read the design in full.
- The README.Quick start, environment, the HTTP API, signing with Kukai and Temple, drum attestation, MCP, Town Hall, VERIFY, the simulator, proofs and Tezos anchoring with measured costs.
- The design notes.The shape of the chain, the determinism rules, accounts and signing modes, every transaction kind, drum attestation, mandates, presence tickets, the state root, the trust model, known gaps and the path to a Tezos rollup kernel.
- v2: Present Company.The v2 plan: four pillars, fourteen packages over seven batches, batch-1 ownership, the demo moment, risks and merge order. Batch 1 is merged; its batch 2–7 list has since been replaced by the Town Network plan.
- Wallets, one profile, passkeys and First Mints.A research and design document, not built code: passkeys as a pass, device passes, one profile, the webauthn signing mode, First Mints recipes, phases and the open questions for Mike.
- Art minting.The pointcast-chain side of the dual-chain gallery: what is possible, the recommendation, the flow, the read API, the SDK, the mirror CLI, failure handling and the steps that need Mike. Local rehearsal.
- pc-sim findings.What the economy simulator measured over 123.1 million applied transactions: every sybil key earns the epoch cap, and only room-attested drums plus tap gating together cut farming from 66% to 10.1%.
- Independent review by Codex.Seven findings, each with a test that failed before the fix, and six follow-ups from Claude’s adversarial pass. Written by Claude from Codex’s tests and notes after OpenAI’s content filter stopped the run.
- Proof of Balance: Codex’s report.What Codex built, how it validated it, the requirement it proved impossible (leaf counts are not authenticated) and the socket-free demo it ran when the sandbox blocked a port.
07 · VERIFY DESK AND EVIDENCE
Catch a lying node on purpose.
VERIFY downloads the consensus code, pinned by sha256, and replays every block in a Web Worker. Only faults that carry checked evidence are blamed on the sequencer, and the evidence is portable: anyone with the chain’s params can check it offline. The demo node re-seals a tampered state root at #37.
cargo run -p node --example lying_node # 127.0.0.1:8546, local only
# with the dev node still on 8545, open http://127.0.0.1:8545/?api=http://127.0.0.1:8546
# press VERIFY, then download evidence.json from the red banner
curl -s http://127.0.0.1:8546/params > params.json
pointcast-node evidence check evidence.json --params params.json # exit 0 = proven fault, 1 = not evidence 08 · PROOF OF BALANCE · VERIFY-CLAIM
Prove a balance without replaying history.
A claim ties an account to a state root that the sequencer signed in an anchor or a sealed header, bound to the genesis. Verification runs offline and prints its scope: inclusion in a sequencer-signed root, not transition validity or Tezos finality. Built by Codex.
pointcast-node prove <address> --height 200 --db data/chain.sqlite > claim.json
pointcast-node verify-claim claim.json --params params.json --genesis <trusted-genesis-hash> 09 · THE ART MIRROR · LOCAL REHEARSAL
Check a Tezos sale before anything is signed.
After a 1 tez sale on Tezos, the mirror checks the operation (applied, two successor blocks, the payment, the token
transfer from a house seller) and only then plans a free first-collector certificate on pointcast-chain. Without
--yes nothing is signed or journaled. No certificate has been issued, and none is promised.
pointcast-node art mirror --tezos-op <op-hash> --contract KT1… --token-id 0 \
--pay-to KT1… --seller tz2… --drop coffee-mug-0 --db data/art-mirror.sqlite # plan only
scripts/art-demo.sh # live smoke on 127.0.0.1:8596, dev keys