from feed to feed.
A technical specification for turning the six loudest voices on the tape into an on-chain, verifiable feed of PnL cards — funded by trading fees on $RHFARM.
Contents
§01 · Thesis
Thesis & design goals
Crypto Twitter runs on unverifiable claims. Screenshots of wins. Deleted losses. Sub-tweets. The market pays attention anyway, because the alternative — reading raw wallet activity — is too slow to trade on.
rhfarm.xyz proposes a different primitive: a permissioned index of six wallets (nominative fair-use, publicly linked) whose realized PnL is snapshotted every 60 seconds and minted as on-chain NFTs. The card exists whether the whale wanted it or not. The whales become the herd.
Four design goals govern every choice in this document:
- Verifiability — every card must be reconstructible from public Robinhood Chain state.
- Idempotency — the pipeline can crash mid-tick and resume without minting duplicates.
- No custody of whale funds — the protocol only reads wallets, never signs on their behalf.
- Fee alignment — mint costs are covered by $RHFARM trading fees, never external subsidy.
§02 · Architecture
System architecture
Six services, one queue, one treasury. Every arrow in the diagram is a Robinhood Chain RPC call, a Redis push, or a signed transaction. No off-chain magic.
The system is deliberately boring: Python workers, PostgreSQL for state, Redis for the tick queue, a single hot wallet for mint signing, and a cold multisig for the treasury. All of it is horizontally shardable per whale if the tick rate ever needs to drop below 60s.
§03 · Ingestion
Ingestion — the RH Chain indexer reader
The reader pulls the six tracked wallets (the "Six Head of the Pool") and hydrates each with the last 60 seconds of confirmed transactions. Wallet handles map to EVM addresses in a versioned registry; changing the registry is a governance event.
# rhindex.py — one tick, six wallets, ~40 RPC calls async def tick(kols: list[Wallet], rpc: HeliusClient) -> Tick: slot = await rpc.get_slot(commitment="confirmed") fills = [] for k in kols: sigs = await rpc.signatures_for(k.pubkey, until=k.cursor) for sig in sigs: tx = await rpc.parsed_tx(sig) fill = parse_swap(tx, k.pubkey) # RH router, RhinoSwap, RH launchpad AMM if fill: fills.append(fill) k.cursor = sigs[0].signature if sigs else k.cursor return Tick(slot=slot, fills=fills, ts=now_utc())
The parser understands RH router v1, RhinoSwap AMM & CLMM, RH launchpad bonding curve, and RhinoMarket AMM (graduated). Other routes are stored as "unknown swap" and excluded from PnL until a decoder ships. Fills carry `route`, `mint_in`, `mint_out`, `amount_in`, `amount_out`, `price_usd_at_slot`, and the source signature — enough for a third party to reproduce the number.
§04 · Accounting
Snapshotter — realized PnL per tick
For each whale and each ERC-20 token they touch, the engine keeps a FIFO lot book. Buys open lots; sells close the oldest lots first and emit realized PnL in USD at the slot's swap-implied price. Unrealized PnL is computed for the dashboard but never minted — cards are always realized.
# pnl_engine.py — FIFO realization def realize(book: LotBook, fill: Fill) -> Decimal: if fill.side == "BUY": book.open_lot(fill.qty, fill.price_usd, fill.slot) return Decimal(0) # SELL — walk oldest lots until qty consumed remaining, pnl = fill.qty, Decimal(0) while remaining > 0 and book.lots: lot = book.lots[0] take = min(lot.qty, remaining) pnl += take * (fill.price_usd - lot.cost_basis) lot.qty -= take remaining -= take if lot.qty == 0: book.lots.popleft() return pnl.quantize(Decimal("0.01"))
Every 60s the engine emits a Snapshot: { kol_id, slot, pnl_24h, pnl_lifetime, win_rate, hold_median, volume_24h, mint_root }. The mint_root is a Merkle root over all fills that fed the snapshot — anyone can reconstruct the same number from raw chain data.
| Field | Type | Purpose |
|---|---|---|
| kol_id | u8 | Registry index (0–5) |
| slot | u64 | Robinhood Chain block at snapshot |
| pnl_24h | i64 (USDC-6) | Realized PnL, rolling 24h |
| win_rate | u16 (bps) | Closed positions in profit / total |
| hold_median | u32 (sec) | Median holding time, closed lots |
| volume_24h | u64 (USDC-6) | Sum of fill notionals, 24h |
| mint_root | [u8; 32] | Merkle root over source fills |
§05 · Mint
Card mint — ERC-721 NFTs
A card is a ERC-721 asset. One asset per snapshot per whale. ERC-721 (not Token Metadata) is chosen for three reasons: single-account layout (lower rent), native plugins, and lower CU cost per mint (~40% cheaper than legacy pNFT flows in current benchmarks).
// mint_worker.ts — one card, one signature const asset = generateSigner(umi); await create(umi, { asset, name: `${kol.handle} · §${snap.slot}`, uri: arweaveUri, // JSON metadata + Merkle proof plugins: [ { type: 'Attributes', attributeList: [ { key: 'pnl_24h', value: snap.pnl_24h.toString() }, { key: 'win_rate_bps', value: snap.win_rate.toString() }, { key: 'volume_24h', value: snap.volume_24h.toString() }, { key: 'mint_root', value: bs58.encode(snap.mint_root) }, { key: 'slot', value: snap.slot.toString() }, ]}, { type: 'PermanentFreezeDelegate', frozen: false }, { type: 'Royalties', basisPoints: 250, creators: [treasury] }, ], }).sendAndConfirm(umi);
Metadata JSON on IPFS carries: the Merkle proof for each source fill, a rendered PNG of the card, the whale registry entry, and a canonical link back to rhfarm.xyz/card/<asset>. Rendering is deterministic — same snapshot input, same PNG bytes, verifiable by any client.
§06 · Treasury
Treasury guardrails
The treasury is a Safe multisig holding fees swept from $RHFARM trading. The mint hot wallet is a separate signer, funded only in just-in-time drips. If the hot wallet drains, mints halt; the pipeline never overdrafts.
- Mint precondition — hot balance ≥ (rent + priority fee + safety) for the tick.
- Cap — 60 cards total lifetime supply (10 per whale). Once hit, minting is permanently disabled at the program level.
- Fee sweep — every 6 hours, RhinoSwap fee accounts flush to treasury via a keeper.
- Emergency pause — a 2-of-3 signature can freeze mints for up to 72h; longer requires token-holder vote.
§07 · Dispatch
The Notice — dispatch layer
Every mint fires "The Notice": a fan-out to Twitter (image + card link), a push topic subscribers can opt into, and a WebSocket message on wss://rhfarm.xyz/notice. The Notice is side-effectful but not authoritative — the card exists on chain whether or not the tweet lands.
# notice_bus.py — post once, retry with jitter async def notice(card: MintedCard): body = render_notice(card) await gather( twitter.post(body.text, media=body.png), # v2 API push.publish("notice", body.json), # APNs / FCM ws.broadcast("/notice", body.json), # dashboard return_exceptions=True, ) log_notice(card.asset, body.hash)
Rate limits: at most one Notice per whale per 5 minutes. Batching kicks in during rip periods — instead of 6 back-to-back tweets, the bus consolidates into a single "§rip" post with all six cards.
§08 · Token
$RHFARM tokenomics
$RHFARM launches on RH launchpad and graduates to RhinoSwap. Trading fees route to the treasury multisig. There is no pre-mine, no allocation, no team unlock schedule — the token is fair-launched and the treasury only exists because the market feeds it.
The card index leg is optional: once all 60 cards mint, holders can vote to airdrop a $RHINDEX token 1:1 to $RHFARM wallets, backed by the card collection held in treasury. This turns the cards into a tradeable basket rather than 60 disconnected NFTs. The vote is non-binding until quorum (>15% supply) is reached.
§09 · Verify
Verifiability & open data
Nothing on rhfarm.xyz should require trust in this document. Every claim above resolves to a public artifact:
| Artifact | Where | How to verify |
|---|---|---|
| Token mint | — awaiting launch — | Robinhood Chain explorer |
| whale registry | /api/registry.json | Diff against RH Chain indexer |
| Live ticks | /api/tick/latest | Replay from Helius signatures |
| Card assets | ERC-721, IPFS | Fetch → recompute Merkle root |
| Treasury balance | Safe multisig | Robinhood Chain explorer |
| Source of numbers | Merkle-rooted per snapshot | Reproduce PnL from raw fills |
§10 · Forward
Roadmap & risks
Roadmap
- Phase 0 · Now — site, registry, whitepaper, $RHFARM launched on RH launchpad.
- Phase 1 · Ingestion — RH Chain indexer reader live for the four linked wallets; unlinked whales remain "—" until pubkeys are attested.
- Phase 2 · Snapshotter — FIFO engine, Merkle roots, public /api/tick/latest replay endpoint.
- Phase 3 · Mint pipeline — ERC-721 deploy, first card minted at token graduation.
- Phase 4 · The Notice — Twitter + push + WS fan-out enabled.
- Phase 5 · Index leg — holder vote on $RHINDEX airdrop after the 60th card.
Risks & mitigations
- whale wallet spoofing — mitigated by requiring on-chain attestation (signed message) before a wallet enters the registry.
- Price-oracle attack on PnL — swap-implied prices are taken from the fill itself, not an external oracle; a whale routing through a manipulated pool poisons only their own card.
- RPC availability — reader is multi-provider (Helius primary, Shyft fallback, Triton backup). A 3-provider quorum protects against silent forks.
- Hot wallet compromise — mint program checks a treasury-controlled PDA; a stolen hot key cannot mint past its just-in-time drip balance.
- Legal / nominative fair use — the six handles are used descriptively, not as endorsements. whales may request removal; a governance vote decides whether to honor the request or fork the registry.