§ Internal memo
How it works
- Re
- Private network indexer for pump.fun, exposed over MCP.
- Rev
- pre-release
- Status
- Closed. Public release soon.
- Handling
- Read once.
§00 Abstract
A private indexer for one program on one chain. inkmaw listens below the RPC layer, rebuilds pump.fun state from raw shreds and Geyser streams, keeps every bonding-curve change in one slot-ordered log, and hands that log to agents as MCP tools. No chart, no feed. Only questions with answers: who funded this dev, is this launch bundled, what did the curve do in this slot, does this event match a rule written in plain words.
turbine shreds --+
+--> decode --> SLOT LOG
geyser / grpc ---+ |
+-----------------+-----------+---------+
| | |
curve state funding graph bundle index
| | |
+-----------------+---------------------+
|
MCP server
|
agents --> rules --> armed [soon]
§01 Ingest
Two sources, merged into one order. Turbine first: shreds come off the wire, erasure sets are recovered and entries reassembled before the block is replayed, so transaction order is known early. Then Yellowstone Geyser over gRPC: account and transaction subscriptions scoped to the pump.fun program, its global config, its fee recipients and every bonding-curve PDA seen so far. Shreds give order early; Geyser gives truth. Where they disagree, Geyser wins and the shred-derived event is retracted, never patched.
shreds udp / turbine
> fec.recover > entry.assemble > tx.decode
geyser grpc / yellowstone subscribe {
accounts owner == PUMP
transactions include [PUMP]
commitment processed
}
merge key (slot, tx_idx, ix_idx)
dedupe | retract on mismatch | upgrade
§02 Decode
Only instructions that touch the program are decoded: create, buy, sell, set-params and the migration out of the curve. Each becomes a typed event keyed by slot, transaction index and instruction index. Inner instructions are walked, so a buy routed through an aggregator or a CPI wrapper still lands as a buy against the curve. Failed transactions are kept. A reverted snipe is evidence too.
ix event key
create Launch (slot, tx, ix)
buy CurveDelta+Fill (slot, tx, ix)
sell CurveDelta+Fill (slot, tx, ix)
set_params ConfigDelta (slot, tx, ix)
migrate Migration (slot, tx, ix)
failed tx Attempt (slot, tx)
§03 Curve state
A bonding curve is four reserves and a flag. Price is never stored; it is derived from reserves at read time, so nothing drifts. Every event becomes a signed delta. Deltas fold into per-mint state that replays from any slot, and two replays from the same slot must agree byte for byte, or the mint is quarantined.
struct CurveDelta {
slot u64
tx_idx u32
ix_idx u16
mint Pubkey
signer Pubkey
d_vsol i128 // virtual SOL
d_vtok i128 // virtual token
d_rsol i128 // real SOL
d_rtok i128 // real token
complete bool // curve filled
commit processed | confirmed | finalized
}
§04 The slot log
One append-only log, ordered by (slot, tx_idx, ix_idx). Processed events are provisional; their commitment is upgraded in place to confirmed, then finalized. When a slot is skipped or a fork abandoned, history is not rewritten: the log emits a tombstone for every event that slot produced, and every consumer tailing it sees the retraction arrive in order, like any other event.
slot tx ix kind mint commit
s+0 014 02 create 7Hq..pump processed
s+0 015 00 buy 7Hq..pump processed < dev
s+0 016 00 buy 7Hq..pump processed < b1
s+0 016 01 buy 7Hq..pump processed < b2
s+0 017 00 buy 7Hq..pump processed < b3
s+1 --- -- tomb s+0/016..017 fork
§05 Funding graphs
For every create, the dev wallet is walked backwards through SOL transfers until the walk reaches a known exchange hot wallet, a bridge, a fan-in shaped like a mixer, or the depth limit. The graph is cached and grows each time a launch reuses a funder. Clusters form around shared funders, shared rent payers and timing too regular to be human. A fresh dev with an old funder is the most common shape in the graph, and the most informative.
[cex hot] --> w1 --> w2 --+--> DEV --> create(mint)
|
+--> b1 --+
+--> b2 --+--> buy(mint)
+--> b3 --+ slot s+0
one tip
§06 Bundle detection
A launch is flagged as bundled when buys in its creation slot, and the slots right after it, share two or more of: contiguous transaction indices behind a single Jito tip, a funder inside the graph, identical compute-unit limits and prices, the same token-account creation layout, a signer set seen together before. The report carries evidence, not a score. An agent can reject the flag and still use the facts.
> bundle.inspect("7Hq..pump")
{
bundled: true,
create_slot: s+0,
linked_buyers: [b1, b2, b3],
evidence: [funder:w2, tip:single,
cu:identical, ata:layout],
dev_in_cluster: true,
cluster_supply: 0.41
}
§07 MCP surface
The indexer speaks the Model Context Protocol. Any MCP-capable agent can attach, list the tools, call them and hold a stream open across slots. Tools are read-mostly and return structured objects, never prose. The two that act are marked soon.
curve.state(mint) -> CurveState
curve.deltas(mint, from?) -> stream<CurveDelta>
events.tail(filter, from?) -> stream<Event>
wallet.funding(addr, depth?) -> Graph
wallet.cluster(addr) -> Cluster
dev.history(dev) -> Launch[]
bundle.inspect(mint, slots?) -> BundleReport
rules.compile(text) -> Rule | CompileError
rules.backtest(rule, slots) -> Trace soon
rules.arm(rule, signer) -> Handle soon
§08 Plain words, compiled
Strategies are written the way a trader would say them out loud. The compiler grounds every noun against the index (dev, funder, bundle, curve, migration), turns every adjective into a predicate with an explicit threshold, and refuses what it cannot ground. The output is a rule: a deterministic predicate over the slot log, plus an action. The compiled rule is shown in full before it is armed. An ambiguous word is a compile error, not a guess.
> "buy new coins whose dev was funded by a fresh
wallet, skip anything bundled, get out the
moment the dev moves."
rule r_7f3a {
on create(mint)
when dev.funding.hops <= 2
and dev.funding.age < 10m
and not bundle.flagged(mint, slots 0..2)
do buy(mint, 0.25 SOL, slippage <= 8%)
exit transfer(dev -> *) or sell(dev, mint)
}
§09 Runtime
Armed rules evaluate on the provisional stream and are re-checked on confirmation. A rule that fired on an event later tombstoned is recorded as a false fire, with the slot that killed it. Every decision leaves a trace: the event, each predicate’s value at that slot, the action. From a sentence to a running rule takes hours, not a sprint.
trace r_7f3a @ s+0 / tx 015
dev.funding.hops 2 ok
dev.funding.age 6m ok
bundle.flagged false ok
action buy queued
confirm s+0 ok
if tombstoned false fire, slot kept
§10 Non-goals
No charts. No social feed. No leaderboard. No dashboard to stare at. The index is built for agents, and agents answer to the wallet that armed them.
charts no
feed no
leaderboard no
dashboard no
opinions no
§11 Access
Closed for now. Every wallet that connects goes into the draw for early seats. Public release soon.
status closed
seats draw, per connected wallet
release public, soon
— end of memo —