Every match here was signed by both players, and this browser checked each of those
signatures itself — the BIP-340 verifier in schnorr.js recomputes each event id
and tests the signature against the signer's own key. Nothing is counted on a relay's word. A
match counts only when the two players named inside the result are the two keys that signed it,
and both signed byte-identical bytes.
Anything that failed is listed, not dropped. Every result that was refused appears under the table with the reason, because a ladder that quietly discards results looks exactly like one that is broken.
Sats are real money. A sat (satoshi) is the smallest unit of Bitcoin, so a staked match is two adults betting their own funds, wallet to wallet. Staking is optional and off unless both players agree it beforehand — the game itself is free, and nothing on this board needs a single satoshi.
Sats staked is what both players signed up to at the start of the match, before either knew how it would go — it is not proof that anyone paid. It counts only when the two keys that signed the start are the same two the result names. Settlement is wallet to wallet over Lightning and this site never touches it. Rating is Elo, K=24, everyone starts at 1500, replayed oldest match first so two browsers reading the same events get the same table.
And here is what this cannot tell you. Every signature above is real, but nothing proves a match was ever played: two keys that agree can publish a result for a game that never happened, and both start at 1500, so anyone willing to make fresh keys can manufacture wins. Nor can it see a match somebody walked away from — an abandoned game simply produces no result at all. Read this as a verified record of what people signed, not a ranking of who is best. Closing that gap needs a referee to co-sign the transcript it refereed, which is designed and not yet built.
| Rank | Player | Rating | W / L / D | Matches | Sats staked |
|---|
Right click a player on a desktop, press and hold on a phone, for their full public key — so you can look the same events up yourself.
Reading the relays…
A player appears here once both seats of a finished match have published the same signed result to a relay this browser can reach. Playing the match is what publishes it; nothing else writes to this board, and no row here can be typed in by hand.
- Relays asked:
—. Add?relay=wss://…to this page's address to read the ladder off a different one. - Results are nostr kind
31600, taggedt=600b-timelock-tcgand addressed byd=<matchId>. Any nostr client can read the same record; this page is only one reader of it.
0 results not counted
Local tools
Below the ladder, and separate from it: a scratch board held in this browser only. It counts what you hand it — a match pulled from a referee, or a JSON file you import — and it is not the signed record above. Nobody else sees it and nothing here changes a rating.
RefereeChecking for a referee…
| Rank | Player | Wins | Losses | Sats won | Sats lost | Net sats |
|---|
This browser holds no records of its own. There are two ways to put one here, and neither of them touches the ladder above:
- Pull a finished match — paste a match id. The board asks this page's referee for
/api/match/<id>and takes the winner, the loser and the referee's own replay verdict straight from the signed result. - Import a JSON file — an array of records, or an object with a
resultsarray. Useful for a record set collected somewhere other than this referee.
Nothing is written here automatically, and clearing the board clears it for good.
Why a pulled match lands at zero sats. The referee records who won, how many turns it
took and the hashes that let anyone replay the transcript. It never records the stake, because
the stake is not on the table: a zap duel is settled wallet to wallet over Lightning, and this
software never holds, escrows or moves a satoshi. So a match pulled from the referee lands with
settledSats: 0 until a record carrying the agreed amount is imported for it.
Record shape. id, winner, loser,
settledSats (a whole number of sats, zero or more), verified: true and
createdAt. A player is either a hex pubkey string or an object with
pubkey and name. Anything that fails those checks is counted by nobody.
Where it lives. In this browser only, under 600b:match-results — or,
when this page runs inside a napplet shell, in that shell's own storage under the same name
and inside the same 512 KB the rest of the game shares. NPC practice games carry no standing
and belong on no leaderboard.
TIMELOCK_TCG :: 600BKIND 31600 · ELO K=24 · VERIFIED LOCALLY