Bots & automation
OpenSwap is built for unattended trading — but with one hard rule at its
core: **a script or an AI may suggest a trade, but only your written policy
can approve one.** A policy is a small JSON file of limits you set once:
which assets, which destination, how much per trade, how much per day. If a
proposed trade breaks any rule, it's rejected cleanly (exit code 4) and
your loop just moves on.
Setting up your policy
openswap bot init
That walks you through the choices interactively and can test the result against live routes on the spot. A finished policy looks like this:
{
"version": 1,
"name": "my-strategy",
"mode": "enforce", // "monitor" logs violations without blocking
"assets": { "allow_from": ["ARB.USDC-0x…"], "allow_to": ["BTC.BTC"] },
"protocols": { "allow": ["chainflip", "near"] },
"destinations": { "allow": ["bc1q…"] },
"limits": {
"max_trade_usd": 250,
"max_daily_volume_usd": 1000,
"max_total_fee_usd": 5,
"max_quote_age_seconds": 20,
"cooldown_seconds": 60
},
"kill_switch_file": "./STOP" // create this file and everything halts
}
One important behavior: unknown values fail closed. If a route's USD value or fees can't be priced, and one of your limits depends on it, the trade is rejected. The policy never guesses in your favor's opposite.
The loop
A working bot is five commands:
openswap watch -a 100 -f arb:USDC -t btc:BTC --jsonl # 1. live price feed
openswap bot check --policy p.json … --json # 2. would this trade pass? (no side effects)
openswap bot run --policy p.json … --json # 3. execute — simulates by default
openswap bot run --policy p.json … --json --live # 4. execute for real
openswap status <receipt> --json # 5. watch it finish
bot run binds quotes to your signer's address, filters to your allowed
protocols, checks the policy, simulates every transaction — and only
broadcasts when you say --live. Retries are safe: an idempotency key
(automatic, or set your own with --idempotency-key) means a retried run
replays the stored result instead of trading twice.
In this release (0.1.x), --live ships disabled while the signing lane
is hardened. Everything else — check, simulated run, the price feed, and
deposit-address bots below — is fully available.
The signer
Live bot trades on EVM chains sign with a key you configure explicitly:
| Environment variable | Meaning |
| --- | --- |
| OPENSWAP_EVM_PRIVATE_KEY | A hot key (you'll be warned on --live) |
| OPENSWAP_EVM_KEYSTORE + OPENSWAP_EVM_KEYSTORE_PASSWORD | An encrypted keystore — the right choice for real funds |
| OPENSWAP_EVM_RPC_URL | Your own RPC endpoint (serious bots should set this) |
Before anything signs, guards check the target address, the chain id, and that the amount being moved never exceeds what was approved.
Bots without a signer
If your automation pays from external wallet infrastructure instead, use the normal swap flow with a policy attached:
openswap swap --policy p.json --json --yes …
Same policy protection, but you get a deposit address to pay rather than an on-chain signature — this works for every chain, not just EVM.