Every keeper STRC ships, what it calls, and what it gets paid for.
STRC ships five distinct keepers. Each handles one job, each is permissionless, each is paid by the contract it serves.
1. The AI-LP rebalance keeper
Claude Opus 4.7 --plan--> lp-ai-loop.mjs --tx--> Locker.rebalanceLocked(plan)
| |
| +-- emits RebalanceBountyPaid
+-- private mempool +-- pays keeper EOA in ETH
(Flashbots-style)What it does. The flagship keeper. Watches the pool every block, pulls a fresh rebalance plan from Claude, and submits it to V4PositionLocker.rebalanceLocked(). The locker re-positions one of the four dynamic LP NFTs (tight / narrow / medium / wide) so depth follows price. On success, the locker pays the keeper a small bounty in ETH and emits RebalanceBountyPaid.
Where it runs. scripts/keeper/lp-ai-loop.mjs on Railway, periodic loop. Plans are submitted through private-call.mjs which routes through a Flashbots-style private mempool to avoid front-running.
Failure mode. If the plan would violate any locker guardrail (cooldown not elapsed, drift below threshold, range outside policy bounds), the contract reverts and the keeper eats gas. Built-in incentive against bad plans.
2. The WSS mempool keeper
WSS pending-tx feed --> wss-keeper.mjs --> Locker.rebalance(...)
|
+-- fast-fire when a large swap is detected
+-- pre-positions LP a tick ahead of impactWhat it does. A faster sibling to the AI-LP loop. Subscribes to a WebSocket feed of pending transactions and triggers an immediate rebalance the instant it detects a large incoming swap that would push price out of the tight range. By the time the swap lands, depth has already moved.
Where it runs. scripts/keeper/wss-keeper.mjs, also on Railway. Coordinates with the AI-LP loop via a per-tokenId mutex so they don't double-fire on the same NFT in the same block.
Why it's separate. The AI loop optimizes for good; the WSS keeper optimizes for fast. Together they cover both regimes — patient repositioning on quiet markets, instant defense on incoming volume.
3. The compound auto-compound keeper
cron tick --> run-strc-ops.mjs --> Locker.harvestAndCompound()
|
+-- collects fees on locker NFTs
+-- mints those fees as new LP
+-- pays keeper a bountyWhat it does. Periodically calls V4PositionLocker.harvestAndCompound(). The locker collects fees accrued on the four dynamic LP NFTs, splits them per the configured BPS — operations wallet (which sustains keeper gas, Railway / Vercel infra, Supabase, RPC, and the Claude AI inference cost), dividend lane, and compound — then mints the compound slice as fresh liquidity directly into the compound-vault NFTs. The pool gets deeper without anyone adding new capital.
Where it runs. Same Railway host, called from run-strc-ops.mjs on a cooldown timer (compoundCooldownSec). Bounty pays the gas back.
What you see on chain. A HarvestAndCompound event with the breakdown of how much was harvested and how much got compounded.
4. The locker fee-harvest keeper
cron tick --> run-strc-ops.mjs --> Locker.harvest()
|
+-- collects fees only (no compound)
+-- routes to ops wallet + fee router + compound
(ops wallet = infra + AI cost)What it does. The simpler sibling of harvestAndCompound. Calls V4PositionLocker.harvest(), which sweeps fees from the locker NFTs and pushes them to their three destinations — the operations wallet (covers keeper gas, Railway, Vercel, Supabase, RPC, Claude AI inference), the fee router (dividends to holders), and the compound vault — without minting new LP. Used when the operator wants to top up dividends faster than the compound cooldown allows.
Why the ops wallet exists. The protocol runs autonomous infrastructure: a Railway-hosted keeper fleet, Supabase database for plan history and metrics, Vercel-hosted dashboard, paid RPC, and on-demand inference from the Claude API for every rebalance plan. None of this is free. The ops wallet receives a small fixed BPS of every harvest so the system pays for itself indefinitely, instead of relying on the team to subsidize it out of pocket. It is a sustainability fee, not a personal yield stream.
Where it runs. run-strc-ops.mjs, on its own schedule.
5. The dividend distribution keeper
cron tick --> run-strc-ops.mjs --> FeeRouter.distributeEth()
|
+-- ETH balance --> WBTC swap (v4 PM)
+-- WBTC --> DividendTracker.distribute()
|
--> FeeRouter.distributeToken()
|
+-- residual STRC --> swap to WBTC
+-- push to trackerWhat it does. The closing keeper in the loop. Calls STRCEthFeeRouter.distributeEth() (and distributeToken() for any STRC residual). Inside, the router swaps the accumulated balance to WBTC on the same v4 PoolManager and pushes the WBTC into the STRCDividendTracker. Holders then pull-claim whenever they want — minimum claim is 0.001 WBTC.
Where it runs. Same orchestrator. Triggers when accumulated ETH crosses the configured floor or on a fixed cron, whichever fires first.
What you see on chain. EthDistributed, TokenDistributed, and (downstream) DividendsDistributed from the tracker.
The combined picture
trade fills
|
v
+-----------------+
| v4 hook (5%) |
+--------+--------+
|
v
+---------+ | +-----------+
| LP-AI |<--+-->| WSS | keepers 1 & 2
| loop | | keeper | reposition LP
+----+----+ +-----+-----+
| |
+----+ +---------+
v v
+-----------------+
| LOCKER |
+--------+--------+
|
| fees accrued
v
+---------+----------+--------------+
| | |
v v v
+----------+ +----------+ +-------------+
|compound | 3 |fee router| | ops wallet |
| vault |<--------+ | | infra+AI |
|(grows LP)| +-----+----+ | + keeper |
+----------+ | | gas |
^ | 4&5 +-------------+
| harvestAnd- | sustains
| Compound (3) v Railway,
| +----------+ Vercel,
+--------------+ DIV | Supabase,
| TRACKER | RPC, Claude
+----+-----+ inference
|
v
holders pull
WBTC dividendsFive keepers, one consistent contract: protocol pays the work, anyone can do it, the system reverts if you propose something unsafe. Three lanes carry the proceeds — compound deepens the chart, dividends pay holders, and the ops wallet covers infrastructure and AI inference so the system pays for itself indefinitely. The AI is the brain. The hooks are the enforcement. The keepers are the muscles that make the system move, and the ops lane is the metabolism that keeps them fed.