Velocity ProtocolDevelopers
Trading Automation

Trading Automation

This section is for anyone running code that trades or maintains Velocity without a person at the keyboard. Two different jobs live here, and they have different economics.

Keeper bots perform protocol maintenance: matching crossed orders, marking triggered conditional orders, and liquidating unhealthy accounts. They are paid a per-action reward by the protocol, and most need no capital beyond transaction fees. Trading bots run a strategy for their own account, so they carry inventory and can lose money. Velocity ships reference implementations of both in apps/keeper-bots-v2.

Automating orders from an existing service, with no persistent process to run, is the SDK path below rather than either bot family.

Which bot to run

Rewards vary by bot and by the duty performed. Each tutorial states what its bot is paid, and Keeper incentives covers how the protocol funds those payments.

BotKindCapital requiredTutorial
Order matchingKeeperTransaction fees onlyOrder matching bot
Order triggerKeeperTransaction fees onlyOrder trigger bot
LiquidatorKeeperYes, it inherits the positions it liquidatesLiquidation bot
JIT makerTradingYes, it holds inventoryJIT maker bot

The app ships more bots than these four have tutorials for, including a spot filler, a floating maker, a P&L settler, an insurance-fund revenue settler, and several cranks. example.config.yaml lists every name accepted under enabledBots, most of them commented out.

Trading workflows without a bot

A bot is one way to automate. The other is to call the SDK from an existing service. The order below is the dependency order: each step needs the one above it.

  1. Connect. Build a VelocityClient, point it at an RPC endpoint, and subscribe. See SDK setup, then Precision and types before anything touches funds, because every amount is a BN at a fixed precision.
  2. Read markets and oracles. Fetch market metadata and oracle prices, and understand which of them the client caches versus fetches. See Markets.
  3. Fund the account. Deposit collateral and know how withdrawals are gated. See Deposits and withdrawals and Users for the subaccount model.
  4. Place and cancel. Limit, market, oracle, and trigger orders, plus cancels and the cancel-and-place pair. See Orders.
  5. Watch risk. Margin, account health, and unrealized P&L, before and after each action. See P&L and risk.
  6. React to fills. Subscribe to program events rather than polling for state changes. See Events.

The Velocity SDK index carries the same path with an end-to-end code example.

Running a reference bot

The reference bots live in apps/keeper-bots-v2. There is no devnet or mainnet branch split; the ENV value selects the cluster at runtime.

The velocity-v1 monorepo is not public yet. It will be published once the post-fork audit report is final. Until then, ask the team for access to run these bots.

Prepare a wallet and an RPC endpoint

Every bot needs a funded keypair to sign with, and some need collateral on top. See Bot wallet to create one and RPC providers for what the endpoint has to support. Both are worth settling before cloning anything: a free RPC plan without websockets or getProgramAccounts will not run a bot at all.

Install the workspace

git clone <velocity-v1>
cd velocity-v1
bun install   # run once, at the repo root, this is a Bun workspace

Configure

From apps/keeper-bots-v2, copy the env template:

cd apps/keeper-bots-v2
cp .env.example .env

Three values are read from the environment:

  • KEEPER_PRIVATE_KEY: a keypair array, or a path to keypair.json.
  • ENDPOINT: the RPC endpoint.
  • ENV: devnet or mainnet-beta.

The rest is a YAML config; start from example.config.yaml. At minimum set global.endpoint, global.keeperPrivateKey (leave it null to fall back to the env var), the list of bot names under enabledBots, and a matching entry under botConfigs for each one. Secrets that the config file should not carry, the keeper key and the Pyth Lazer token, are read from the environment only; the YAML loader does no variable interpolation.

Initialize a Velocity user, if the bot needs one

Bots that place orders or hold positions need a Velocity user account. The app can create one:

bun run dev --init-user

The equivalent from SDK code:

if (!(await velocityClient.getUser().exists())) {
  logger.info(`Creating User for ${wallet.publicKey}`);
  const [txSig] = await velocityClient.initializeUserAccount();
  logger.info(`Initialized user account in transaction: ${txSig}`);
}

Deposit collateral, if the bot needs it

Liquidators and JIT makers hold positions, so they need collateral before they can do anything. The app exits after the deposit lands, so run it once and then start the bot normally:

# deposit 10,000 of spot market 0's deposit asset
bun run dev --force-deposit 10000

Run and watch

bun run dev --config-file=example.config.yaml

Individual bots also have their own entrypoint scripts, such as bun run dev:filler and bun run dev:trigger, which skip the config file and enable one bot.

Watch the logs for resubscribe messages, which mean the websocket went quiet and the SDK reconnected, and track RPC latency. Bot configs can expose Prometheus metrics on a metricsPort.

Troubleshoot

The failures a new bot hits are usually a missing token account, an uninitialized User, or an RPC that ran out of credits. All three, plus the program error codes worth recognizing, are in Troubleshooting.

Bot wallet

Bots sign their own transactions, so they need a private key on the machine. Velocity's tooling accepts it either as base58 or as a numbers array.

Generate a fresh keypair

  1. Install the Solana CLI.

  2. Create the keypair file:

    solana-keygen new -o new_keypair.json

    The file holds the keypair as a JSON numbers array, the format KEEPER_PRIVATE_KEY expects for an inline key.

Alternatively, export the private key from a browser wallet such as Phantom.

Key security

Treat a bot's key as a production secret:

  • Never commit a keypair file or a raw private key to version control.
  • Load the key from an environment variable or a secret manager rather than a plaintext file on disk.
  • Use a dedicated hot wallet funded only with what the bot needs for fees, and collateral if it holds positions. Do not reuse a wallet that holds anything else.

RPC providers

Solana serves account data through a network of RPC nodes. Running one is expensive, so most bots rent access.

Several free tiers will not work here, because they disable exactly what a bot depends on: websocket subscriptions and getProgramAccounts. The JIT maker, for example, finds fillable orders with programSubscribe (see JIT maker bot), and the SDK's account subscriber holds open websocket subscriptions for perp markets, spot markets, users, and user stats. Confirm a provider supports both before committing to a plan.

Helius has a free plan sufficient to get started, and the bot config has Helius-specific priority-fee support (priorityFeeMethod: helius). Expect to move to a paid plan as throughput grows. A fuller list of providers is here.