Scrip

Docs

What a keeper can and cannot do.

Keepers are permissionless and open source. Anyone can run one; the tip pays them. Their only discretion is the route.

Five lines

The sweep transaction, atomic without a Jupiter CPI

A PDA can only sign inside a CPI, so a top-level Jupiter instruction cannot draw from a program-owned escrow. The slice therefore passes through the keeper’s own USDC account inside one atomic transaction, and the program guarantees — through instruction introspection — that the verifying instruction runs at the end. If it does not, the first instruction refuses; if verification fails, everything reverts, including the delegate transfer.

0  ComputeBudget      unit limit; unit price
1  begin_sweep        compute the slice; delegate-transfer USDC → the keeper
2  Jupiter setup      if any
3  Jupiter swap       USDC → asset, ExactIn = slice, destination = the owner's account
4  Jupiter cleanup    if any
5  finish_sweep       delta ≥ Pyth min-out; receipt; tip — or everything reverts

The price bound

finish_sweep reads a Pyth price account for the book’s asset, fully verified, under ten minutes old, with a confidence band under 1%. The minimum that must arrive is the slice divided by the price plus its confidence, less the owner’s tolerance, in raw units. For a feed that prices one share rather than one token, the minimum is divided by the mint’s live scaled-UI multiplier. Below the minimum, the whole transaction reverts.

Where the price comes from

Hermes has required an API key since 26 August 2026, and the on-chain SPYX/USD account was not being kept fresh when we looked. So a keeper posts its own fully verified update from Hermes when the on-chain one is stale, and closes it after. A stale feed pauses sweeps; nothing is lost by waiting.

Running one

SCRIP_KEEPER_KEYPAIR=keeper.json PYTH_API_KEY=… NEXT_PUBLIC_SOLANA_CLUSTER=mainnet-beta npm run keeper

It watches every Book with the rule on, subscribes to each owner’s USDC account, syncs watermarks after spends, and reports the last sweep and the last reason per book on a health endpoint the app reads.