documentation
One coupon a day.
It matures in a day.
That's the whole mechanism. Everything here is the arithmetic for it, what the reader can and cannot see, and every number that can be changed. If something on the site isn't explained here, that's a bug in this page.
The idea
A holder-rewards distribution usually reads everyone's balance at some moment and splits a pot by what it saw. That asks a person to be holding at an instant, which makes the optimal play buy-just-before and sell-just-after, and the reader cannot tell a month of holding from forty seconds of it.
A coupon is what a bond pays whoever is holding it, and that is the idea borrowed intact: the payment belongs to the holder, and it has to be held to be earned.
Maturity
matured = tokens acquired at least 24 hours ago and still held
Nothing arrives already matured. This applies to a buy, a transfer in, an airdrop, or a rebuy after a sale. Maturity cannot be bought, borrowed or sent, only waited for.
The moment each parcel matures is fixed the instant it arrives, so the whole thing is computable now. Rather than asking anyone to trust that their tokens start earning, the page gives the hour.
Parcels and LIFO
A wallet is not a balance, it is a stack of dated parcels. One number cannot stand for a bag bought at five different times without being wrong about four of them.
When you sell, it comes out of the newest parcels first. Trimming a tenth off the top takes the parcel you bought this morning, not the one you have held since launch.
The day
The day runs from the launch, not from a timezone anybody has to look up. Day zero opens the moment the token exists; day n closes exactly n+1 days later.
The pot for a day is whatever creator fee arrived at the treasury during it, plus whatever rolled over from the day before.
Splitting the pot
Strictly in proportion to matured tokens. No multiplier, no tier, no bonus, no streak bonus and no second term. One number decides everything.
Integer wei throughout; no float anywhere in the path. Integer division leaves a remainder, handed out by largest remainder with the address as a deterministic tiebreak, so two people running this produce byte-identical files.
Payments smaller than the gas to send them are not paid and not kept: they are named in the ledger and roll into tomorrow, so a small holder accumulates rather than receiving nothing indefinitely.
paid + rollover === pot
Asserted before publication and across four hundred randomly generated days in the tests. A day that doesn't balance to the wei doesn't publish.
What it survives
| buying before the close | Earns nothing at that close because the tokens haven't been held a day. They join tomorrow's split, at an hour the page has already given. |
|---|---|
| selling after a close | Works once, for the day actually held. Buying back starts green again. No penalty, no blacklist; you simply pay the day back. |
| splitting across wallets | Weight is linear in matured tokens, so two wallets holding half a parcel each weigh what one wallet holding the parcel weighs. Nothing gained, so nothing policed, and nobody honest flagged by a clustering guess. |
| shuffling to a second address | Strictly worse than doing nothing. Tokens leave one wallet and arrive green in the other, so the pair earns nothing at the next close where one wallet would have earned in full. |
| airdrops in | Arrive green and wait a day like everything else. |
| trimming | Takes the newest parcels first, so an old position is untouched. This is the one thing here that is deliberately generous. |
Supply that survived the night
The same arithmetic, summed over circulating supply: the share of every token that has sat in the same wallet for a full day.
It cannot be staged for a screenshot. A wallet that buys this morning to inflate it contributes nothing until tomorrow, by which time the screenshot is old.
Circulating supply is minted, less burned, and less anything sitting in an excluded address: the pool and the treasury, which are configured rather than detected. A distributor that tries to work out what a contract is will eventually decide a real holder is one.
Stubs and streaks
A wallet's stubs, including how many days it has been paid and its current streak, are read back out of the published ledgers rather than kept in memory. A streak here is a fact about files anyone can download, not a counter this process is holding.
Streaks pay nothing. They are a record, not a multiplier, because a multiplier would be a second rule and the whole point is that there is one.
What it reads, and what it can't
Balances are rebuilt from Transfer logs, which are deltas, not
balances. Miss one and the number is wrong forever and nothing inside the
reconstruction would ever notice.
So every wallet is checked against a live balanceOf before anyone is paid. A
wallet whose reconstruction disagrees is held back. It is named in the ledger and paid
nothing that day rather than being paid on a number nobody can stand behind.
A coupon doesn't care why a balance moved, so this needs no swap decoding and no venue-specific event shape. It only needs to know when a balance changed, which is the one thing a transfer log actually says. That makes this reader considerably harder to break than one that has to understand a DEX.
Events are folded in strict time order; a read that arrives out of order stops rather than being sorted over, because a reconstruction that has quietly reordered itself is wrong somewhere else too.
Where the pot comes from
Pons takes 1% of every swap and splits it 70/30 with the creator. The creator's side is claimed in ETH to one address, and the pot is whatever has actually arrived there.
| fee asset transfers | Fees paid in a token: Transfer logs into
the treasury. Exact, cheap and complete. |
|---|---|
| native transfers | A block scan for transactions paying the treasury. Value forwarded inside a contract call doesn't appear in a block's transaction list, so this mode reports itself incomplete rather than quietly under-counting. |
| claim list | Curated claim hashes, each verified on chain: exists, didn't revert, pays the treasury, moves value. The fallback that always works. |
Money leaving is never counted, only money arriving. It is not money from new buyers. nothing to stake, nothing to lock, no contract holding anyone's tokens.
The ledger
State is not a database. It is the stack of published days, and everything carried between them is recomputed from those files on every boot. A day is published once; a correction is a new day with a note, never a quiet edit to an old one.
It goes up before the money moves, so anyone who saved a copy can hold it against the payment transactions afterwards. Every wallet holding the token is in it, with a reason:
| whole bag matured | every token has been held a full day |
|---|---|
| part of the bag is still maturing | with the hour the rest joins |
| nothing matured, bought inside the day | earns at the next close |
| under the send floor, rolled forward | smaller than the gas to send it |
| held back | reconstruction disagreed with the chain |
Settings
| RPC_URL | JSON-RPC endpoint, read from the environment at boot. No request can influence it. An endpoint that fetches a URL somebody handed it is an SSRF with better manners, and there is no flag to turn the guard off. |
|---|---|
| TOKEN | the coin |
| POOL | the Pons pair. Excluded from the standing. |
| TREASURY | where the creator fee is claimed to. Also excluded. |
| FROM_BLOCK | the block the token was created in |
| LAUNCH | unix seconds the token launched. The day clock starts there; if it is not given, the first transfer the reader saw is used. |
| FEE_ASSET | the asset fees arrive in, or native |
| CLAIM_TXS | optional claim hashes, each verified on chain |
| EXCLUDE | optional extra addresses to leave out of the standing |
| RIPEN_HOURS | how long a parcel takes to mature. Default 24. The only real parameter there is. |
| DAY_HOURS | how long a day is, for the close. Default 24. |
| MIN_PAY | the send floor in wei |
| LEDGER_DIR | where closed days live. Default ./ledgers |
The API
GET only. A POST gets a 405 and nothing else. Amounts travel as exact decimal strings alongside their raw wei, never as JSON numbers.
| /api/day | the open day: pot, source, every claim transaction, supply that survived the night, the full standing, when it closes, and whether it balances |
|---|---|
| /api/book?addr= | one wallet: every parcel, which have matured, what is still ripening and when, its stubs, and what this close pays it |
| /api/token | market figures labelled as read from a public venue; fees claimed, distributed and rolling |
| /api/ledger.csv | the ledger as a file |
| /healthz | ok |
No lookup is written to disk. There is no route that takes free text and returns generated text, and none that can be made to fetch something on a caller's behalf.
Running it
node test-book.mjs # the book, the maturity and the split node test-http.mjs # the routes, and the promises the source has to keep node dev.js # local preview, invented history, real engine RPC_URL=… TOKEN=… POOL=… TREASURY=… FROM_BLOCK=… node live.js node close.js d41 → ledgers/d41.json replayed by the next day → out/d41-ledger.csv the human-readable record → out/d41-pay.csv address, amount, for your own wallet
Zero dependencies. Node's standard library and nothing else. The pages load no font and no script from anybody else, because a page that says it isn't tracking you and then calls a CDN has broken that promise before it finishes rendering.
What it holds
Nothing.
No keys. No signing. No connect-wallet button, no account, no record of who looked up what. There is no route in this codebase that can spend anything, and the test suite greps its own source for private keys, seed phrases and signing calls and fails the build if it finds one.
close.js writes a file. A person sends the payments from their own wallet, on
their own machine. Every custody failure in this category began with something that held
funds briefly on someone's behalf.
Known edges
- A sale and a transfer look identical. Deliberately. Any distinction would be a rule somebody could work around; tokens leaving your address end their parcel, and that is the whole classification.
- A day is enough. Someone can buy, hold one day, take one close and leave. That is the advertised deal, not a hole in it.
- LIFO lets you churn the top of a bag without touching an old position. It costs a fee on every round trip and earns nothing, so it is expensive noise rather than an exploit, but it is worth knowing it is possible.
- Pool and treasury are configured, not detected. Get them wrong and they appear in the standing as enormous holders.
- Circulating supply is inferred from mints, burns and excluded balances. If a deployer holds supply in an unlisted address, it counts as circulating.
- Streaks pay nothing. They are a record. If that ever changes it becomes a second rule, and the whole argument for this design is that there is one.
Rewards depend on fees earned. Nothing here is financial advice.