Workflows
A trigger and up to 20 steps on a project's wallets: swaps, orders, waits, perps, bridges, strategy stages, private sends and more, run on ftw.trade's servers with every step's state and outputs kept.
A workflow is when this happens, do these steps. It runs on ftw.trade's servers once armed, on paper or live as its project is, and keeps every step's state, outputs and log.
Every hour, a random wallet makes a random swap#
{ "name": "Hourly random swap",
"trigger": { "kind": "timer", "every": "1h" },
"steps": [{ "id": "swap", "kind": "swap", "side": "either", "unit": "percent",
"amount": "${random(2, 10)}", "wallets": { "groups": ["fleet"] }, "pick": 1,
"pools": ["robinhood:0x…", "robinhood:0x…"] }] }pick: 1 takes one wallet of the group at random, side: "either" flips a coin, random(2, 10) draws the percent, and pools picks the market.
Triggers#
| Trigger | Fires |
|---|---|
| Manual | When you press Start |
| Price | Once a pool's price or market cap crosses a value after arming |
| Timer | Every period, from a minute to a week, until stopped |
| Signal | On the next event of a source whose fields match ({ spread: { gt: 20 } }), or on every one |
| Strategy metric | When a running strategy's metric crosses a value |
| Launch | When one of your project's launches is on chain, or graduates |
| New launches | A sniper: every matching new launch on a launchpad gets its own run. See Snipers and launches |
Steps#
| Step | Does |
|---|---|
swap | Buys or sells now across wallets, optionally with take-profit, stop and trailing exits resting on the wallets that bought |
order | Rests a limit order, done at its first fill |
wait, watch | Waits some minutes, or until a pool crosses a value or a launch graduates |
strategy | Runs a saved strategy on the wallets; with until it's a stage that ends when the strategy says so and hands on its metrics |
flowscript | Runs a strategy once over the latest bars and outputs its metrics |
perp, deposit, withdraw | Perps orders (including "hold this position"), and USDC in or out of a venue |
bridge | Moves funds between chains by the best route |
husher | Fans ETH out privately to wallets, or sends it privately home, and waits until it lands |
pool, index, launch | Makes a Uniswap pool, indexes a new one, or sends one of the project's token launches |
group, buyWallets | Rotates wallets between roles, or buys aged wallets from the marketplace into one |
remember, emit, poll, action | Keeps a value in project memory, publishes an event, refreshes a source, or calls a script action (a Telegram post, say) |
Steps run one after another unless after says otherwise, so steps after the same one run together.
Outputs and expressions#
Each step's outputs are typed, and later steps read them: "${entry.mcapUsd * 3}", "${spot.usd / spot.wallets}", "${memory.losses}". Expressions are checked when the workflow is saved, so a pool goes where a pool goes and a number where a number goes.
Any step can run only when something holds:
{ "id": "alert", "kind": "action", "name": "telegram", "args": { "text": "BTC under ${pos.price}" },
"when": { "value": "${pos.price}", "lt": 60000 } }Arm, run, stop#
- A workflow is armed when saved: it waits for its trigger. Start runs it now.
- It fires once; arm it again to rerun. Repeating workflows (a timer, or a signal with
repeat) re-arm themselves, run one at a time, keep every run's history, and stop after three failed runs in a row. - A step that fails ends the run and says why. Steps that wait on something slow (a private send, a wallet purchase) report a status instead (
done,partial,failed,expired) so later steps can branch on it. - Orders and strategies a workflow started keep running after it ends.
A step or a script?#
Use a built-in step whenever one says what you need: swaps, orders, perps, bridges, pools and ranges run at once, checked against what was already sent. Write a TypeScript script for the rest: an outside API, data no source carries, or bespoke logic.