optimizer

module
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 14, 2026 License: MIT

README

Catscope Optimizer

Run a web assembly bot that will run in the Catscope runtime over Solpipe. A local Solpipe bidder daemon sets up a gRPC tunnel to a validator. The Optimizer code base talks with the local Solpipe bidder daemon to access the target Validator (Pipeline=2Gi87bD2MNKFREReqkJgcLodkBuQEcYGKaaWz45i2Nbo). The main event loop is in ./brain/simple/simple.go.

The rest of this page describes how to run the optimizer. This involves setting up Safejar and Solpipe CLI tools, creating some onchain accounts, and connecting to the validator.

Download Solpipe

Download a Docker image with Safejar and Solpipe command line tools.

Linux (Debian Trixie)
sudo apt-get update \
  && sudo apt-get install -y wget gnupg build-essential curl \
    pkg-config \
    libudev-dev llvm libclang-dev \
    protobuf-compiler libssl-dev \
  && wget -O- https://noncepad.com/keys/nightly/trixie.sources > /tmp/sources \
  && sudo mv /tmp/sources /etc/apt/sources.list.d/noncepad.trixie.sources \
  && sudo apt-get update \
  && sudo apt-get install -y solpipe
Docker
docker build -t solpipe:nightly https://noncepad.com/keys/nightly/Dockerfile
Mac OS
brew install noncepad/homebrew-tap/noncepad-solpipe

To do an upgrade:

brew upgrade noncepad-solpipe

Prerequisite

We must separate the main custody of funds from the bidder daemon that automatically pays USD for API access. Set up a Jar, an onchain Solana account that controls funds like a treasury.
The Jar owner controls all funds, so owner signatures need to be done on a special PC. For starting out, we can ignore this requirement. Once the Jar has been created, we will then delegate funds to the Bidder daemon on a market by market basis.

WALLET=usb://ledger?key=10
JAR_OWNER=usb://ledger?key=20
safejar --fee-payer=$WALLET jar $WALLET
  • fund $WALLET with 0.05 SOL to start

For small amount of funds, just use a file based private key:

solana-keygen new -o ./owner.json
solana-keygen new -o ./wallet.json
safejar --fee-payer=./wallet.json jar ./owner.json
  • set the variable JAR_ID from the output of safejar jar init
  • fund the system account ./authorizer.json with SOL for transaction fees and account rent

Run daemon

The bidder daemon is a background process that handles a soft wallet, pipeline auction budgets, and proxies gRPC connections to pipelines. This must be running for the commands below to work.

Run the daemon:

solpipe --fee-payer=./authorizer.json bidder proxy ./proxy.json -v

The daemon is accessible at:

  • management socket: $HOME/.solpipe.bidder.manage.sock
  • gRPC proxy socket: $HOME/.solpipe.bidder.proxy.sock

Interact with the daemon with the command in a separate terminal:

solpipe bidder tui

Join Bot Market

For each market place, the user needs to:

  1. create a Safejar delegation account using a rule set derived by the bidder daemon
  2. instruct the bidder daemon to join the market place
  3. set a budget cap and pipeline allocation.
    • to connect to pipelines for free idle capacity, just set the budget cap to 0
  4. programmatically adjust the portfolio and budget
Delegate funds (ie Set Policy)

Safejar has a rule sets that govern the spending of token funds from a Delegation account. The goal is to have the bidder daemon be able to participate in Validator auctions to gain access to their respective Catscope bot runtimes.

MARKET=6VQk8GA84p7zZSyL8XtX6oVd3Vp4EJ5hoUenKoC3fHSf
solpipe bidder propose-rule-set $MARKET

An example output is:

Jar: EV4AHRFZDjVwgytVj77xEtGgTvdNfePJdwPiJSBjMiTf
Authorizer: 8L3PJAJTZu2Gx54h7KHNGvpTwxq7TxZkZeSVxXAnCi7m
Market: 6VQk8GA84p7zZSyL8XtX6oVd3Vp4EJ5hoUenKoC3fHSf
PcMint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Decimal: 41
Proposed Rule Set: ( RateLimiter(EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,3000,7200) && AuthorizationConstraint(5CnV9KB5qMkmXcU2hUMHshVCstrppqr7NXjRX1Wg6z7m) ) || SweepV2(EV4AHRFZDjVwgytVj77xEtGgTvdNfePJdwPiJSBjMiTf,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,100)
  • copy ( RateLimiter(EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,3000,7200) && AuthorizationConstraint(5CnV9KB5qMkmXcU2hUMHshVCstrppqr7NXjRX1Wg6z7m) ) || SweepV2(EV4AHRFZDjVwgytVj77xEtGgTvdNfePJdwPiJSBjMiTf,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,100) as the rule set
safejar --fee-payer=$WALLET delegation init $JAR_OWNER 1 --rule="( RateLimiter(EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,3000,7200) && AuthorizationConstraint(5CnV9KB5qMkmXcU2hUMHshVCstrppqr7NXjRX1Wg6z7m) ) || SweepV2(EV4AHRFZDjVwgytVj77xEtGgTvdNfePJdwPiJSBjMiTf,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,100)"

Sample output:

A delegation account has been created for jar: EV4AHRFZDjVwgytVj77xEtGgTvdNfePJdwPiJSBjMiTf
  delegation account: GwE9Yt9K5X31kTs6HXaMHwMMGBHrjoGxSAbXaFFh1ZKA
  jar token account:  CpWtZMR5us4FFm4CFLzQDz1wMFuJzguTS9XeFWtQ4XB3
  mint:               EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
Proxy to Market
solpipe bidder listen "( RateLimiter(EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,3000,7200) && AuthorizationConstraint(5CnV9KB5qMkmXcU2hUMHshVCstrppqr7NXjRX1Wg6z7m) ) || SweepV2(EV4AHRFZDjVwgytVj77xEtGgTvdNfePJdwPiJSBjMiTf,EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,100)" 6VQk8GA84p7zZSyL8XtX6oVd3Vp4EJ5hoUenKoC3fHSf

Once the command exits, the bidder daemon will automatically connect to the pipelines service the gRPC protobuf.

TUI

Interact with the daemon with:

solpipe bidder tui

Run Optimizer

The optimizer code actually compiles the code automatically. The code that does that is in ./prefetch/rust.go Build function. The reason the optimizer compiles the Catscope Rust Bot is that the optimizer statically compiles chain state into the web assembly binary to save on validator bot runtime memory and time.

The optimizer is an example of how to programmatically:

  1. set a budget allocation for different pipelines (in this example, no USD/hour and 1 pipeline); see ./brain/arbv1
  2. connect to the single pipeline
  3. upload a bot to this pipeline (which sits in front a validator bot runtime)
  4. run the bot and see stderr output

Build optimizer:

echo $BOT_IMAGE
cd $HOME/work/optimizer
solana-keygen new -o ./fee-payer.json
go build -o ./optimizer ./cmd
  • the fee payer is also the trading wallet

Run the optimizer:

./optimizer arb ./fee-payer.json
  • Set BOT_IMAGE to the file path of the compiled web assembly bot

Directories

Path Synopsis
brain
arbv1
Package arbv1 is the Go-side orchestrator for the arbv1 (arbitrage v1) bot mode.
Package arbv1 is the Go-side orchestrator for the arbv1 (arbitrage v1) bot mode.
testperpv1
Package testperpv1 is the Go-side orchestrator for the testperpv1 bot mode -- a real-transaction smoke test, not a real trading strategy.
Package testperpv1 is the Go-side orchestrator for the testperpv1 bot mode -- a real-transaction smoke test, not a real trading strategy.
Package bundler defines account bundling schemes
Package bundler defines account bundling schemes
astralane
Package astralane wraps bundler functionality
Package astralane wraps bundler functionality
jito
Package jito wraps jito
Package jito wraps jito
examples
eino-ollama-agent command
Command eino-ollama-agent is a minimal example of building a tool-calling agent with github.com/cloudwego/eino.
Command eino-ollama-agent is a minimal example of building a tool-calling agent with github.com/cloudwego/eino.
telnet command
Command harness is a minimal tool-calling agent, built the same way as go-wiki/examples/eino-ollama-agent/main.go (github.com/cloudwego/eino's prebuilt ReAct agent: call the model -> if it asked for a tool, run the tool and feed the result back -> repeat until the model answers without a tool call), but with walletTools() (see tools.go) in place of that example's demoTools().
Command harness is a minimal tool-calling agent, built the same way as go-wiki/examples/eino-ollama-agent/main.go (github.com/cloudwego/eino's prebuilt ReAct agent: call the model -> if it asked for a tool, run the tool and feed the result back -> repeat until the model answers without a tool call), but with walletTools() (see tools.go) in place of that example's demoTools().
Package portfolio persists bot balance snapshots (each tagged with the token's USD price at capture time) to a local SQLite database, and computes PnL from them.
Package portfolio persists bot balance snapshots (each tagged with the token's USD price at capture time) to a local SQLite database, and computes PnL from them.
Package prefetch builds wasm bots preloaded with necessary information
Package prefetch builds wasm bots preloaded with necessary information
alt
Package alt persists Address Lookup Table contents to prefetch.db -- see cmd/alt.go, the only writer.
Package alt persists Address Lookup Table contents to prefetch.db -- see cmd/alt.go, the only writer.
drift
Package drift preloads Drift v2 SpotMarket accounts (global market data only -- User, the per-wallet position account, is not fetched here since there is no bounded set to bulk-load, and PerpMarket is skipped since it has no mint/vault of its own -- perp markets settle in the program's quote asset).
Package drift preloads Drift v2 SpotMarket accounts (global market data only -- User, the per-wallet position account, is not fetched here since there is no bounded set to bulk-load, and PerpMarket is skipped since it has no mint/vault of its own -- perp markets settle in the program's quote asset).
jet
Package jet preloads Jet Protocol V1 lending pool reserve accounts (global market data only -- Obligation, the per-wallet position account, is not fetched here since there is no bounded set to bulk-load).
Package jet preloads Jet Protocol V1 lending pool reserve accounts (global market data only -- Obligation, the per-wallet position account, is not fetched here since there is no bounded set to bulk-load).
kamino
Package kamino preloads Kamino Lending reserve accounts.
Package kamino preloads Kamino Lending reserve accounts.
liquidity
Package liquidity generates router.json for the catscope-rust-bot build.
Package liquidity generates router.json for the catscope-rust-bot build.
lst-yield
Package lstyield estimates real Solana liquid-staking-token (LST) staking yield from a periodic SOL-per-LST exchange-rate timeseries, so an LST-collateral leverage-loop strategy (originally built as leveragedloopv1's Time-Expanded DAG, since removed) has a real profitability signal to work from.
Package lstyield estimates real Solana liquid-staking-token (LST) staking yield from a periodic SOL-per-LST exchange-rate timeseries, so an LST-collateral leverage-loop strategy (originally built as leveragedloopv1's Time-Expanded DAG, since removed) has a real profitability signal to work from.
marginfi
Package marginfi preloads marginfi-v2 Bank accounts (global market data only -- MarginfiAccount, the per-wallet position account, is not fetched here since there is no bounded set to bulk-load).
Package marginfi preloads marginfi-v2 Bank accounts (global market data only -- MarginfiAccount, the per-wallet position account, is not fetched here since there is no bounded set to bulk-load).
mintinfo
Package mintinfo provides a small shared cache of SPL Mint decimals, populated opportunistically by every prefetcher that discovers a mint (Orca, Raydium AMM/CPMM/CLMM) so a mint referenced by many pools (USDC, wSOL) is only ever fetched once per run, not once per pool.
Package mintinfo provides a small shared cache of SPL Mint decimals, populated opportunistically by every prefetcher that discovers a mint (Orca, Raydium AMM/CPMM/CLMM) so a mint referenced by many pools (USDC, wSOL) is only ever fetched once per run, not once per pool.
obligation
Package obligation records this bot's own Solend/Kamino lending obligation state (deposits/borrows, across multimodelv1's pair/ directional/hawkes trade types, since removed) into prefetch.db, the same skip-if-unchanged shape optimizer/prefetch/pnl uses for wallet token balances -- see this package's schema.sql for the real motivation (there was previously no way to see this state without manually deriving each obligation's address and parsing its raw account bytes).
Package obligation records this bot's own Solend/Kamino lending obligation state (deposits/borrows, across multimodelv1's pair/ directional/hawkes trade types, since removed) into prefetch.db, the same skip-if-unchanged shape optimizer/prefetch/pnl uses for wallet token balances -- see this package's schema.sql for the real motivation (there was previously no way to see this state without manually deriving each obligation's address and parsing its raw account bytes).
orca
Package orca preloads Orca Whirlpool trading pools.
Package orca preloads Orca Whirlpool trading pools.
phoenix
Package phoenix preloads Phoenix perpetuals market identity (symbol, asset_id, market_account) into prefetch.db.
Package phoenix preloads Phoenix perpetuals market identity (symbol, asset_id, market_account) into prefetch.db.
pnl
Package pnl records a trading wallet's token position history into prefetch.db and computes mark-to-market PnL from it: the market value of a position at its earliest known snapshot vs.
Package pnl records a trading wallet's token position history into prefetch.db and computes mark-to-market PnL from it: the market value of a position at its earliest known snapshot vs.
price-feed
Package pricefeed polls the Jupiter Price API v3 for a configurable list of token mints and publishes price updates on a channel.
Package pricefeed polls the Jupiter Price API v3 for a configurable list of token mints and publishes price updates on a channel.
pumpfun
Package pumpfun preloads Pump.fun bonding-curve state.
Package pumpfun preloads Pump.fun bonding-curve state.
pumpswap
Package pumpswap preloads PumpSwap AMM pool state.
Package pumpswap preloads PumpSwap AMM pool state.
raydium
Package raydium preloads Raydium AMM v4 trading pools.
Package raydium preloads Raydium AMM v4 trading pools.
raydium/amm
Package amm tracks amm
Package amm tracks amm
raydium/clmm
Package clmm tracks clmm
Package clmm tracks clmm
raydium/cpmm
Package cpmm tracks cpmm
Package cpmm tracks cpmm
sanctum
Package sanctum preloads Sanctum S Controller LST pool state.
Package sanctum preloads Sanctum S Controller LST pool state.
solend
Package solend preloads Solend/Save token-lending reserve accounts (global market data only -- Obligation, the per-wallet position account, is not fetched here since there is no bounded set to bulk-load).
Package solend preloads Solend/Save token-lending reserve accounts (global market data only -- Obligation, the per-wallet position account, is not fetched here since there is no bounded set to bulk-load).
trading
Package trading holds common structs
Package trading holds common structs
Package shell sets up a telnet endpoint
Package shell sets up a telnet endpoint
Package store persists prefetched on-chain data to a local SQLite database.
Package store persists prefetched on-chain data to a local SQLite database.
Package util contains generic functions.
Package util contains generic functions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL