Keepers are off-chain agents that monitor the Symmetry protocol and execute pending tasks in exchange for bounties. All keeper operations are permissionless — every SDK method in the rebalance flow (Documentation Index
Fetch the complete documentation index at: https://docs.symmetry.fi/llms.txt
Use this file to discover all available pages before exploring further.
updateTokenPricesTx, flashSwapTx, mintTx, redeemTokensTx, claimBountyTx, etc.) can be called by any wallet. The keeper parameter is simply the signing wallet.
Developers can build their own keeper bots using the individual SDK methods directly. The SDK also ships with KeeperMonitor and RebalanceHandler as reference implementations that handle the full lifecycle automatically — use them as-is, or as a starting point for custom keeper logic.
KeeperMonitor
KeeperMonitor is a reference keeper implementation included in the SDK. It continuously polls the protocol and automatically handles:
- Executing configuration intents after activation
- Cancelling expired intents
- Processing rebalance intents (price updates, flash swaps, minting, redeeming, bounty claims)
Setup
Running
Continuous loop:run() method calls update() every ~30 seconds, stops after the specified duration, waits 45 seconds for in-flight tasks, then clears internal state.
How It Works
Eachupdate() call:
- Fetches all vaults and syncs them to an internal map.
- Fetches all configuration intents. For new intents, starts
monitorIntent()in the background. - Fetches all rebalance intents. For new actionable ones (not
deposit_tokensornot_active), startsmonitorRebalanceIntent()in the background. - Removes closed intents from internal maps.
Intent Monitoring
For each configuration intent:- Wait until
activation_timestamp. - Try to execute via
executeVaultIntentTx(up to 2 attempts). - If execution failed, wait until expiration.
- After expiration, try to cancel via
cancelVaultIntentTx(up to 4 attempts).
Rebalance Intent Monitoring
For each rebalance intent:- Skip if
not_activeordeposit_tokens(waiting for user action). - If
update_prices: callupdateTokenPricesTx(up to 5 attempts). - During auction windows:
- Compute swap pairs via
getSwapPairs. - Fetch Jupiter quotes for profitable pairs (refreshed every 60 seconds).
- Execute
flashSwapTxfor each profitable pair. - Re-check every ~8 seconds.
- Compute swap pairs via
- After auctions end:
- Deposits: call
mintTx(up to 3 attempts). - Withdrawals with remaining tokens: call
redeemTokensTx(up to 3 attempts). Note: if the recipient’s ATA doesn’t exist for a token and the keeper is not the owner, that token is skipped during redemption. Ensure the withdrawer has ATAs for all expected tokens. - Then: call
claimBountyTx(up to 3 attempts).
- Deposits: call
Requirements
| Requirement | Details |
|---|---|
| SOL balance | Keeper wallet needs SOL for transaction fees |
| Jupiter API key | Required for flash swap quotes on mainnet |
| RPC connection | Reliable RPC with sufficient rate limits |
| Uptime | Keepers should run continuously to not miss tasks |
RebalanceHandler
RebalanceHandler handles a single rebalance intent from start to finish. Use this when you want to process a specific rebalance rather than monitoring all protocol activity.
One-Shot Run
Manual Control
Bounty System
Keepers earn bounties for completing tasks. Bounties are funded by the user or manager who creates the intent.How Bounties Work
- When a deposit, withdrawal, rebalance, or configuration change is created, a bounty is deposited (typically in WSOL). This includes a bounty bond — a fixed amount (set in the protocol’s global config as
bounty_bond_amount) that is locked alongside the bounty. - The bounty has a schedule: starts at
min_bountyand increases tomax_bountyover time, incentivizing faster execution. - Each task completion (price update, flash swap, mint, redeem) is recorded on-chain with the keeper’s pubkey and timestamp.
- After all tasks are done,
claimBountyTxdistributes bounties to all participating keepers proportionally based on the tasks they completed. - Unused bounty and the bounty bond are returned to the depositor.
- The on-chain account rent is also returned.
Bounty Schedule
min_bounty_until and max_bounty_after, the bounty interpolates linearly.
Bounty Computation
The total WSOL locked when creating a deposit, withdrawal, or rebalance is computed automatically by the SDK. It includes:| Component | Description |
|---|---|
| Bounty bond | Fixed lock amount from global config (bounty_bond_amount). Returned after completion. |
| Task bounties | max_bounty_per_task × number of tasks (auction stages, mint/redeem, claim). |
| Price update bounties | max_bounty_per_task / bounty_per_price_update_task_divisor × number of tokens in the vault. More tokens = more price update instructions = higher total. |
min_bounty_amount and max_bounty_amount parameters in buyVaultTx, sellVaultTx, and rebalanceVaultTx. Higher bounties incentivize keepers to process operations faster.
The SDK computes the total automatically — callers do not need to calculate it manually.
Adding Bounty to a Vault
Vault bounty funds automation (keeper-initiated rebalances):Jupiter Integration
The SDK includes utilities for interacting with Jupiter for flash swaps:Swap Modes
| Mode | Description |
|---|---|
exact_in | Guarantee exact input amount, variable output |
exact_out | Guarantee exact output amount, variable input |
ioc | Immediate-or-cancel — best effort execution |
The Jupiter API call uses reversed mint directions internally. The SDK handles this — you specify
vaultMintIn (what the vault receives) and vaultMintOut (what the vault gives), and the SDK swaps them for the Jupiter query.