TypeScript scripts
Hosted TypeScript with @ftw/sdk for what Flowscript and workflow steps don't do: outside APIs, signals, actions other scripts call, and bespoke logic, sandboxed and held to a policy you approve.
A script is TypeScript that belongs to a project and runs on ftw.trade, in a sandbox: QuickJS in WebAssembly, a fresh runtime each run. No Node, no filesystem, no network except to hosts its policy names, and never a wallet key.
There are three kinds:
| Kind | Made with | Does |
|---|---|---|
| Automation | automation() | Runs on triggers and trades through wallet handles |
| Source | source() | Publishes typed events. See Sources |
| Action | action() | A function other scripts and workflows call by name, with typed arguments and answer |
An automation#
import { automation } from '@ftw/sdk';
export default automation({
name: 'Dip buyer',
triggers: [{ pool: 'base:0x…', below: 0.0021 }, { every: '5m' }],
policy: { wallets: ['w1'], maxEthPerTrade: 0.05, maxEthPerDay: 0.2 },
async run(ctx, event) {
if (event.type !== 'price') return;
const fill = await ctx.wallets.get('w1').buy({ token: '0x…', eth: 0.05 });
ctx.log.info('bought the dip', fill);
ctx.metric('price', event.price);
},
});Triggers#
{ every: "1s" … "7d" }on a schedule;{ pool, above?, below? }when a price crosses a line;{ signal, where? }on a source's events;{ socket }on a websocket's messages;- and always by hand.
The policy#
You approve a script's policy when you deploy it, and every call is checked against it:
| Field | Limits |
|---|---|
wallets | Which wallets it may trade (none means read-only) |
maxEthPerTrade, maxEthPerDay | How much it may spend |
tokens | Which tokens it may touch |
egress | Which hosts ctx.fetch may reach |
secrets | Which of your secrets it may use (as {{secrets.NAME}} in a request, never as a value it can read) |
live | Whether it may trade a live project |
bridge | The most one move may bridge |
What a script can do#
ctx.wallets.get(id) buys, sells, bridges and reads balances; ctx.pools reads prices, candles, swaps and liquidity; ctx.fetch calls allowed hosts; ctx.state keeps 64 KB between runs; ctx.signal and ctx.emit publish; ctx.actions.call calls an action; ctx.log and ctx.metric report.
Every effect (a buy, a bridge, an outside call, a signal) is journaled per delivery, so a run that's retried never repeats one.
Versions and deploys#
Each save is a version; deploying one asks you to approve its policy. Push from your machine with ftw-trade push src/*.ts --project <id> --deploy. Every run's log, metrics and emitted rows are kept, and a project's dashboards can chart them.
Flowscript, workflow or script?#
| You want to | Use |
|---|---|
| Decide on bars and trade | A Flowscript strategy |
| Do things in order when something happens | A workflow |
| Filter or transform a stream | A Flowscript source |
| Call an outside API, or anything bespoke | A script |